<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Heee's Development Blog</title>
    <description>Step by step goes a long way.</description>
    <link>http://gmlwjd9405.github.io/</link>
    <atom:link href="http://gmlwjd9405.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 26 Nov 2019 15:05:15 +0000</pubDate>
    <lastBuildDate>Tue, 26 Nov 2019 15:05:15 +0000</lastBuildDate>
    <generator>Jekyll v3.8.5</generator>
    
      <item>
        <title>[JUnit] JUnit5 사용법 - Parameterized Tests</title>
        <description>&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;계속해서 추가할 예정!&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;maven-dependencies&quot;&gt;Maven Dependencies&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.junit.jupiter&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter-params&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.4.2&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;testCompile(&quot;org.junit.jupiter:junit-jupiter-params:5.4.2&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;parameterized-tests&quot;&gt;Parameterized Tests&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@ParameterizedTest&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;이 annotation을 추가하는 것을 제외하고는 다른 테스트와 동일하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;e.g.
    &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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@ValueSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ints&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;MAX_VALUE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// six numbers&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isOdd_ShouldReturnTrueForOddNumbers&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;number&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;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isOdd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;ul&gt;
      &lt;li&gt;6번의 isOdd 메서드를 실행한다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;a source of arguments&lt;/em&gt;: an int array&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;a way to access them&lt;/em&gt;: the number parameter&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;1-simple-value&quot;&gt;1. Simple Value&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@ValueSource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 에 지정한 배열을 파라미터 값으로 순서대로 넘겨준다.&lt;/li&gt;
      &lt;li&gt;test method 실행 당 &lt;strong&gt;하나의 인수(argument)&lt;/strong&gt; 만을 전달할 때 사용할 수 있다.&lt;/li&gt;
      &lt;li&gt;리터럴 값의 배열을 테스트 메서드에 전달한다.&lt;/li&gt;
      &lt;li&gt;c.f. &lt;em&gt;literal values&lt;/em&gt; 종류
        &lt;ul&gt;
          &lt;li&gt;short, byte, int, long, float, double, char, java.lang.String, java.lang.Class&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;e.g. 하나의 인수(String input)만을 가짐
    &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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Strings&lt;/span&gt; &lt;span class=&quot;o&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;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBlank&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;n&quot;&gt;input&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isEmpty&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@ValueSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strings&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;s&quot;&gt;&quot;&quot;&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;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBlank_ShouldReturnTrueForNullOrBlankStrings&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;n&quot;&gt;input&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;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Strings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isBlank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-null-and-empty-values&quot;&gt;2. Null and Empty Values&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@NullSource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;primitive data 는 널(null) 값을 허용할 수 없으므로 primitive 인수에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@NullSource&lt;/code&gt; 를 사용할 수 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@EmptySource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;이 annotation 을 사용하여 빈 값을 인수에 전달할 수 있다.&lt;/li&gt;
      &lt;li&gt;String 인수의 경우 ““(empty string), Collection types 과 Arrays 에도 빈 값을 넣을 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@NullAndEmptySource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;null 값과 empty value 모두 전달하기 위해 해당 annotation 을 사용할 수 있다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@EmptySource&lt;/code&gt;와 마찬가지로 문자열, 컬렉션 및 배열에서 동작한다.&lt;/li&gt;
      &lt;li&gt;몇 가지 빈 문자열 변형을 parameterized test 로 전달하기 위해 &lt;strong&gt;@ValueSource, @NullSource 및 @EmptySource&lt;/strong&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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@NullAndEmptySource&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBlank_ShouldReturnTrueForNullAndEmptyStrings&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;n&quot;&gt;input&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;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Strings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isBlank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-enum&quot;&gt;3. Enum&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@EnumSource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;enumeration(열겨형) 값의 배열을 테스트 메서드에 전달한다.&lt;/li&gt;
      &lt;li&gt;test method 실행 당 &lt;strong&gt;하나의 인수(argument)&lt;/strong&gt; 만을 전달할 때 사용할 수 있다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;names&lt;/em&gt; 속성
        &lt;ul&gt;
          &lt;li&gt;리터럴 문자열 외에도 정규 표현식(regular expression)을 &lt;em&gt;names&lt;/em&gt; 속성에 전달할 수 있다.&lt;/li&gt;
          &lt;li&gt;기본적으로 &lt;em&gt;names&lt;/em&gt; 속성은 일치하는 enum 값을 가진다.&lt;/li&gt;
          &lt;li&gt;mode 속성을 &lt;strong&gt;EXCLUDE&lt;/strong&gt; 로 설정하면 제외하는 enum 값을 가질 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;e.g. 모든 월(Month enum)을 확인하여 월 숫자가 1과 12 사이에 있는지 확인하는 경우
    &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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@EnumSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// passing all 12 months&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getValueForAMonth_IsAlwaysBetweenOneAndTwelve&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&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;monthNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;monthNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;monthNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;/li&gt;
  &lt;li&gt;e.g. 월의 ‘이름’ 속성을 사용하여 특정 개월만 선택하는 경우 (4, 6, 9, 11월의 기간이 30일인지 확인)
    &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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@EnumSource&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&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;s&quot;&gt;&quot;APRIL&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JUNE&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SEPTEMBER&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;NOVEMBER&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;someMonths_Are30DaysLong&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&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;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isALeapYear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isALeapYear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;/li&gt;
  &lt;li&gt;e.g. 2, 4, 6, 9, 11월을 &lt;strong&gt;제외&lt;/strong&gt;한 월의 기간이 31일인지 확인하는 경우
    &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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@EnumSource&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;names&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;s&quot;&gt;&quot;APRIL&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JUNE&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SEPTEMBER&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;NOVEMBER&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FEBRUARY&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnumSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Mode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;EXCLUDE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;exceptFourMonths_OthersAre31DaysLong&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Month&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&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;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isALeapYear&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertEquals&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;month&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isALeapYear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;4-method&quot;&gt;4. Method&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@MethodSource&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;위의 argument sources들은 복잡한 object를 사용하여 전달하는 것이 어렵거나 불가능하다. 보다 복잡한 인수를 제공하는 방법 중 한 가지는 method를 argument source로 사용하는 것이다.&lt;/li&gt;
      &lt;li&gt;즉, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@MethodSource&lt;/code&gt;는 test method 실행 당 &lt;strong&gt;복잡한 인수&lt;/strong&gt; 를 전달할 때 사용하는 방법이다.
        &lt;ul&gt;
          &lt;li&gt;test method 호출 당 하나의 인수(argument)를 전달하는 경우는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Arguments&amp;gt;&lt;/code&gt; 추상화를 사용하지 않아도 된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@MethodSource&lt;/code&gt; 에 설정하는 이름은 존재하는 메서드 이름이어야 한다.
        &lt;ul&gt;
          &lt;li&gt;이름을 설정하지 않으면 JUnit은 test method와 이름이 같은 source method를 찾는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;argument source method 조건&lt;/em&gt;&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&amp;lt;Arguments&amp;gt;&lt;/code&gt; (혹은 Iterable, Iterator) 또는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List와 같은 컬렉션&lt;/code&gt;과 유사한 interface 를 반환할 수 있다.&lt;/li&gt;
          &lt;li&gt;클래스 단위 생명 주기가 아닌 경우, static method 여야 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@MethodSource&lt;/code&gt;를 이용하면 다른 테스트 클래스 간에 인수를 공유하는 것이 유용하다.
        &lt;ul&gt;
          &lt;li&gt;이 경우 정규화된 이름 (&lt;em&gt;FQN#methodName format&lt;/em&gt;)으로 현재 클래스 외부의 source method 를 참조할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;e.g. 기본 사용 예제 - 복잡한 인수(String input, boolean expected)를 가짐
    &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;@ParameterizedTest&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@MethodSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;provideStringsForIsBlank&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// needs to match an existing method.&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBlank_ShouldReturnTrueForNullOrBlankStrings&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;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&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;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Strings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isBlank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&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;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;c1&quot;&gt;// a static method that returns a Stream of Arguments&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;provideStringsForIsBlank&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;// argument source method&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&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;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&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;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Arguments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;not blank&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;e.g. 외부 source method 참조 예제
    &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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringsUnitTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nd&quot;&gt;@ParameterizedTest&lt;/span&gt;
      &lt;span class=&quot;nd&quot;&gt;@MethodSource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.baeldung.parameterized.StringParams#blankStrings&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 클래스 외부의 source method&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource&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;n&quot;&gt;input&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;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Strings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isBlank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringParams&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&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;nf&quot;&gt;blankStrings&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&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;span class=&quot;s&quot;&gt;&quot;  &quot;&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JUnit5의 기본적인 사용법에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/11/26/junit5-guide-basic.html&quot;&gt;JUnit5 기본 사용법&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/parameterized-tests-junit-5&quot;&gt;Guide to JUnit 5 Parameterized Tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Wed, 27 Nov 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/11/27/junit5-guide-parameterized-test.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/11/27/junit5-guide-parameterized-test.html</guid>
        
        <category>java</category>
        
        <category>test</category>
        
        <category>junit</category>
        
        <category>junit5</category>
        
        
      </item>
    
      <item>
        <title>[JUnit] JUnit5 사용법 - 기본</title>
        <description>&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;계속해서 추가할 예정!&lt;/span&gt;&lt;/p&gt;

&lt;h3 id=&quot;maven-dependencies&quot;&gt;Maven Dependencies&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.junit.jupiter&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter-engine&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.1.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;testRuntime(&quot;org.junit.jupiter:junit-jupiter-engine:5.1.0&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;1-기본-annotation&quot;&gt;1. 기본 Annotation&lt;/h3&gt;
&lt;h4 id=&quot;beforeall-and-beforeeach&quot;&gt;@BeforeAll and @BeforeEach&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@BeforeAll&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 메서드가 현재 클래스의 모든 테스트 메서드보다 먼저 실행된다.&lt;/li&gt;
      &lt;li&gt;해당 메서드는 static 이어야 한다.&lt;/li&gt;
      &lt;li&gt;이전의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@BeforeClass&lt;/code&gt; 와 동일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@BeforeEach&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 메서드가 각 테스트 메서드 전에 실행된다.&lt;/li&gt;
      &lt;li&gt;이전의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Before&lt;/code&gt; 와 동일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@BeforeAll&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&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;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@BeforeAll - executes once before all test methods in this class&quot;&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;nd&quot;&gt;@BeforeEach&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&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;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@BeforeEach - executes before each test method in this class&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;h4 id=&quot;displayname-and-disabled&quot;&gt;@DisplayName and @Disabled&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@DisplayName&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;테스트 클래스 또는 테스트 메서드의 이름을 정의할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@Disable&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;테스트 클래스 또는 메서드를 비활성화할 수 있다.&lt;/li&gt;
      &lt;li&gt;이전의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Ignore&lt;/code&gt; 와 동일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@DisplayName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Single test successful&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testSingleSuccessTest&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;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Success&quot;&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;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Disabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Not implemented yet&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testShowSomething&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;aftereach-and-afterall&quot;&gt;@AfterEach and @AfterAll&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@AfterAll&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 메서드가 현재 클래스의 모든 테스트 메소드보다 이후에 실행된다.&lt;/li&gt;
      &lt;li&gt;해당 메서드는 static 이어야 한다.&lt;/li&gt;
      &lt;li&gt;이전의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@AfterClass&lt;/code&gt; 와 동일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@AfterEach&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 메서드가 각 테스트 메서드 이후에 실행된다.&lt;/li&gt;
      &lt;li&gt;이전의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@After&lt;/code&gt; 와 동일&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@AfterAll&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;done&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;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@AfterAll - executed after all test methods.&quot;&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;nd&quot;&gt;@AfterEach&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tearDown&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;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@AfterEach - executed after each test method.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;h3 id=&quot;2-assertions-and-assumptions&quot;&gt;2. Assertions and Assumptions&lt;/h3&gt;
&lt;h4 id=&quot;assertions&quot;&gt;Assertions&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.junit.jupiter.api.Assertions&lt;/code&gt;로 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;assertTrue, assertThat&lt;/strong&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;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lambdaExpressions&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;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&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;na&quot;&gt;stream&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;na&quot;&gt;mapToInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;na&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sum should be greater than 5&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;/li&gt;
  &lt;li&gt;&lt;strong&gt;assertAll&lt;/strong&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;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;groupAssertions&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;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertAll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;numbers&quot;&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assertAll()&lt;/code&gt;을 사용하여 assertions 을 그룹화하여 그룹 내에서 실패한 assertions 을 MultipleFailuresError 와 함께 기록할 수 있다.&lt;/li&gt;
      &lt;li&gt;즉, 실패의 정확한 위치를 정확히 파악할 수 있기 때문에 보다 복잡한 assertions 을 만들어도 안전하게 사용할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;assumptions&quot;&gt;Assumptions&lt;/h4&gt;
&lt;ul&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;assumptions 이 실패하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TestAbortedException&lt;/code&gt;이 발생하고 테스트는 수행되지 않는다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;assumeTrue(), assumeFalse(), and assumingThat()&lt;/strong&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;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;trueAssumption&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;assumeTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&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;nd&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;falseAssumption&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;assumeFalse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&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;nd&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assumptionThat&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;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Just a string&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;assumingThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;someString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Just a string&quot;&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-exception-testing&quot;&gt;3. Exception Testing&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;assertThrows()&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;두 가지 예외 테스트 방법
    &lt;ul&gt;
      &lt;li&gt;모두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assertThrows()&lt;/code&gt; 메서드를 사용하여 구현할 수 있다.
        &lt;ol&gt;
          &lt;li&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;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shouldThrowException&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;nc&quot;&gt;Throwable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assertThrows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Not supported&quot;&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;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Not supported&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;/li&gt;
          &lt;li&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;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assertThrowsException&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;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;assertThrows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IllegalArgumentException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&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;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;            &lt;/div&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;4-test-suites&quot;&gt;4. Test Suites&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@SelectPackages&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Test Suites 를 실행할 때 선택할 패키지 이름 지정
        &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;@RunWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;JUnitPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@SelectPackages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.baeldung&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AllUnitTest&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@SelectClasses&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Test Suites 를 실행할 때 선택할 클래스 지정
        &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;@RunWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;JUnitPlatform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@SelectClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AssertionTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AssumptionTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExceptionTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AllUnitTest&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;/li&gt;
      &lt;li&gt;각 테스트는 하나의 패키지에 있지 않아도 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;5-dynamic-tests&quot;&gt;5. Dynamic Tests&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@TestFactory&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 메서드는 동적 테스트를 위한 &lt;em&gt;test factory 메서드&lt;/em&gt;이다.&lt;/li&gt;
      &lt;li&gt;런타임에 생성된 테스트 케이스를 선언하고 실행할 수 있다.&lt;/li&gt;
      &lt;li&gt;e.g. 각각 in, out 이라는 두 개의 ArrayList 를 사용하여 단어를 번역한다.
        &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;@TestFactory&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DynamicTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;translateDynamicTestsFromStream&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&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;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;DynamicTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dynamicTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Test translate &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&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;o&quot;&gt;-&amp;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;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&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;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&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;o&quot;&gt;);&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;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@TestFactory&lt;/code&gt; 메서드는 private 또는 static 이면 안된다.&lt;/li&gt;
      &lt;li&gt;테스트 수는 동적이며, ArrayList 크기에 따라 달라진다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@TestFactory&lt;/code&gt; 메서드는 Stream, Collection, Iterable 또는 Iterator 를 return 해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;6-etc&quot;&gt;6. ETC&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@Nested&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 annotation 이 달린 클래스는 중첩된 비정적(non-static) 테스트 클래스 임을 나타낸다.&lt;/li&gt;
      &lt;li&gt;테스트 클래스 안에서 내부 클래스(Inner Class)를 정의해 테스트를 계층화할 수 있다.&lt;/li&gt;
      &lt;li&gt;내부 클래스로 정의하기 때문에 부모 클래스의 멤버 필드에 접근할 수 있고, Before/After 와 같은 테스트 생명주기에 관계된 메소드들도 계층에 맞게 동작한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@Tag&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;테스트 필터링을 위한 태그를 선언할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@ExtendWith&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;사용자 정의 확장명을 등록하는 데 사용된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@RepeatedTest&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@RepeatedTest(반복횟수)&lt;/code&gt; 를 이용하면 해당 테스트를 반복 실행할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JUnit5 Parameterized Tests의 기본적인 사용법에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/11/27/junit5-guide-parameterized-test.html&quot;&gt;JUnit5 Parameterized Tests 기본 사용법&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/junit-5&quot;&gt;A Guide to JUnit 5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/junit5-dynamic-tests?utm_content=buffer2b72f&amp;amp;utm_medium=social&amp;amp;utm_source=twitter.com&amp;amp;utm_campaign=buffer&quot;&gt;Guide to Dynamic Tests in Junit 5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.journaldev.com/20834/junit5-tutorial&quot;&gt;https://www.journaldev.com/20834/junit5-tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reiphiel.tistory.com/entry/junit5-features&quot;&gt;https://reiphiel.tistory.com/entry/junit5-features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 26 Nov 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/11/26/junit5-guide-basic.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/11/26/junit5-guide-basic.html</guid>
        
        <category>java</category>
        
        <category>test</category>
        
        <category>junit</category>
        
        <category>junit5</category>
        
        
      </item>
    
      <item>
        <title>[IntelliJ] intellij에서 JPA Entitiy 기반의 ERD 그리기</title>
        <description>&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;들어가기 전
      &lt;ul&gt;
        &lt;li&gt;Hibernate를 사용한 프로젝트를 기준으로 설명한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;persistence-tab-설정&quot;&gt;Persistence Tab 설정&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;File &amp;gt; Project Structure &amp;gt; Project Settings &amp;gt; Facets &amp;gt; [+] 버튼 클릭
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-1.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;JPA 선택 &amp;gt; Choose Module 창 &amp;gt; [“ERD를 확인할 프로젝트 명”.main] 선택
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-2.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Project Settings &amp;gt; Modules &amp;gt; 위에서 생성한 JPA 선택
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-3.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Default JPA Provider 를 Hibernate 로 선택
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-4.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;jpa-entity-기반의-erd-확인하기&quot;&gt;JPA Entity 기반의 ERD 확인하기&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;intellij 왼쪽의 Persistence Tab 생성 확인
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-5.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;기본적인-er-diagram-확인&quot;&gt;기본적인 ER Diagram 확인&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Persistence 클릭 &amp;gt; 확인하고자 하는 Entity 구조 우클릭 &amp;gt; ER Diagram 클릭
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-6.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-7.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;조금-더-상세한-erd-확인&quot;&gt;조금 더 상세한 ERD 확인&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;ERD 창 임의의 위치에서 우클릭 &amp;gt; Show Edge Labels 클릭
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-8.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;/images/erd/intellij-erd-9.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 28 Oct 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/10/28/intellij-jpa-erd.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/10/28/intellij-jpa-erd.html</guid>
        
        <category>intellij</category>
        
        <category>jpa</category>
        
        <category>erd</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 값 타입(2) - 컬렉션 타입</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;기본값 타입&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;임베디드 타입 (복합 값 타입)&lt;/strong&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;strong&gt;값 타입 컬렉션&lt;/strong&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;jpa의-최상위-데이터-타입-분류-2가지&quot;&gt;JPA의 최상위 데이터 타입 분류 (2가지)&lt;/h1&gt;
&lt;h2 id=&quot;1-엔티티-타입&quot;&gt;1. 엔티티 타입&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;@Entity로 정의하는 객체&lt;/li&gt;
  &lt;li&gt;데이터가 변해도 식별자로 지속해서 추적이 가능하다.&lt;/li&gt;
  &lt;li&gt;e.g. 회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식이 가능하다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-값-타입&quot;&gt;2. 값 타입&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;int, Integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체&lt;/li&gt;
  &lt;li&gt;식별자가 없고 값만 있으므로 변경시 추적이 불가능하다.&lt;/li&gt;
  &lt;li&gt;e.g. 숫자 100을 200으로 변경하면 완전히 다른 값으로 대체된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;구체적인-데이터-타입-분류-3가지&quot;&gt;구체적인 데이터 타입 분류 (3가지)&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;기본값 타입
    &lt;ul&gt;
      &lt;li&gt;자바 기본 타입 (int, double)&lt;/li&gt;
      &lt;li&gt;래퍼 클래스 (Integer, Long)&lt;/li&gt;
      &lt;li&gt;String&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;임베디드 타입 (embedded type, 복합 값 타입)
    &lt;ul&gt;
      &lt;li&gt;JPA에서 정의해서 사용해야 한다.&lt;/li&gt;
      &lt;li&gt;e.g. 좌표의 경우, Position Class&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;컬렉션 값 타입 (collection value type)
    &lt;ul&gt;
      &lt;li&gt;마찬가지로 JPA에서 정의해서 사용해야 한다.&lt;/li&gt;
      &lt;li&gt;컬렉션에 기본값 또는 임베디드 타입을 넣은 형태이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2019/09/12/value-type-of-basic-and-embedded.html&quot;&gt;기본값 타입과 임베디드 타입 참고 POST&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;3-값-타입-컬렉션collection-value-type&quot;&gt;3. 값 타입 컬렉션(collection value type)&lt;/h2&gt;
&lt;!-- ![그림 추가]() --&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;값 타입 컬렉션은 값 타입을 &lt;em&gt;하나 이상&lt;/em&gt; 저장할 때 사용한다.&lt;/li&gt;
&lt;/ul&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&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;favoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;ul&gt;
  &lt;li&gt;RDB에는 내부적으로 컬렉션을 담을 수 있는 구조가 없다. 그냥 값만 넣을 수 있는 구조이다.
    &lt;ul&gt;
      &lt;li&gt;컬렉션은 1:N 의 개념이기 때문에 DB는 컬렉션을 하나의 테이블에 저장할 수 없다.&lt;/li&gt;
      &lt;li&gt;이런 관계를 DB 테이블에 저장하려면 &lt;strong&gt;별도의 테이블&lt;/strong&gt;(Join이 가능하도록)이 필요하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; FAVORITE_FOOD, ADDRESS 에서 모든 속성으로 pk로 잡는 이유?
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 해당 테이블은 값 타입인데, 하나를 식별자로 두는 개념을 도입하면 엔티티가 될 수도 있기 때문이다.&lt;/li&gt;
      &lt;li&gt;즉, 테이블에 값들만 저장하고 이들을 묶어서 pk로 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;구현-예시&quot;&gt;구현 예시&lt;/h3&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;nd&quot;&gt;@ElementCollection&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@CollectionTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FAVORITE_FOOD&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;joinColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FOOD_NAME&quot;&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;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&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;favoriteFoods&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;HashSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@ElementCollection&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@CollectionTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ADDRESS&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;joinColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressHistory&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;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&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;ul&gt;
  &lt;li&gt;기본 사용 어노테이션
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ElementCollection&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@CollectionTable&lt;/code&gt; 어노테이션을 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;과정
    &lt;ul&gt;
      &lt;li&gt;Member 클래스에 값 타입 컬렉션을 추가한다.&lt;/li&gt;
      &lt;li&gt;addressHistory는 임베디드 타입이므로 컬럼명들을 그대로 사용하면 된다.&lt;/li&gt;
      &lt;li&gt;favoriteFoods는 String 하나(내가 만든 것이 아님)에 대한 Set이기 때문에 컬럼명을 지정해준다.&lt;/li&gt;
      &lt;li&gt;memberId를 외래키로 지정한다.
        &lt;ul&gt;
          &lt;li&gt;어떤 memberId에 소속되는지 알아야하기 때문에 연관 관계가 필요하다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예제&quot;&gt;예제&lt;/h3&gt;
&lt;h4 id=&quot;컬렉션-값-타입-저장&quot;&gt;컬렉션 값 타입 저장&lt;/h4&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;homeCity&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10001&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10002&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&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;!-- hibernate 쿼리 --&gt;
&lt;ul&gt;
  &lt;li&gt;먼저 Member가 저장되고 값 타입 컬렉션을 저장하는 별도의 테이블에 대한 INSERT Query가 6개 나갔다.
    &lt;ul&gt;
      &lt;li&gt;값 타입 컬렉션(다른 테이블)에 대한 persist를 하지 않았는데 쿼리가 나갔다.&lt;/li&gt;
      &lt;li&gt;즉, Member 객체의 라이프 사이클과 동일하게 적용되었다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why?&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;값 타입이기 때문이다.&lt;/li&gt;
      &lt;li&gt;Member에 소속된 값 타입들의 라이프 사이클은 Member에 의존한다. (별도의 생명주기가 없음)&lt;/li&gt;
      &lt;li&gt;즉, 값 타입은 별도로 persist 또는 update를 할 필요가 없이 Member에서 값을 변경만 하면 자동으로 처리해준다.&lt;/li&gt;
      &lt;li&gt;1:N 연관 관계에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cascade=ALL&lt;/code&gt;로 설정하고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;orphanRemoval=true&lt;/code&gt; 로 설정한 것과 유사하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;c.f. 값 타입 컬렉션은 영속성 전이(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;컬렉션-값-타입-조회&quot;&gt;컬렉션 값 타입 조회&lt;/h4&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;c1&quot;&gt;// ... 위와 동일한 코드 &lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;============ START ============&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// em.persist(member);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&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;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;em.flush()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;em.clear()&lt;/code&gt;로 영속성 컨텍스트를 비운 후 Member를 조회한다.&lt;/li&gt;
  &lt;li&gt;결과
    &lt;ul&gt;
      &lt;li&gt;Member에 소속된 Embedded 타입의 Address 속성은 모두 같이 조회된다.&lt;/li&gt;
      &lt;li&gt;그러나 컬렉션들은 조회 되지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;즉, &lt;strong&gt;컬렉션 값 타입들은 지연 로딩(Lazy Loading) 전략을 취한다.&lt;/strong&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;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;============ START ============&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressHistory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressHistory&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;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;address = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCity&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;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&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;favoriteFoods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&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;n&quot;&gt;favoriteFood&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;favoriteFoods&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;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;favoriteFood = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;favoriteFood&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&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;ul&gt;
      &lt;li&gt;&lt;strong&gt;Why?&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ElementCollection(fetch = LAZY)&lt;/code&gt; 어노테이션의 fetch 기본값이 LAZY 이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;컬렉션-값-타입-수정&quot;&gt;컬렉션 값 타입 수정&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&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;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;============ START ============&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// homeCity -&amp;gt; newCity &lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// findMember.getHomeAddress().setCity(&quot;newCity&quot;); // 틀린 방법 &lt;/span&gt;

  &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;newCity&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStreet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getZipCode&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;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&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;ul&gt;
      &lt;li&gt;값 타입은 불변(Immutable)이어야 한다.&lt;/li&gt;
      &lt;li&gt;따라서, 수정하고 싶은 임베디드 타입의 속성이 있는 경우 새로운 인스턴스를 생성하여 &lt;strong&gt;통으로 갈아 끼워야 한다.&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;e.g. 새로운 Address 인스턴스로 변경&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;컬렉션 값&lt;/strong&gt; 타입 수정 예시1 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set&amp;lt;String&amp;gt;&lt;/code&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;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;============ START ============&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// 치킨 -&amp;gt; 한식 &lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&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;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFavoriteFoods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;ul&gt;
      &lt;li&gt;String은 불변 객체 이므로 삭제하고, 다시 리스트에 넣어준다.&lt;/li&gt;
      &lt;li&gt;String 자체가 값 타입이므로 업데이트를 할 수가 없다. 위와 마찬가지로 통으로 갈아 끼워야 한다.&lt;/li&gt;
      &lt;li&gt;컬렉션의 값만 변경해도 JPA가 변경 사항을 알아 내서 실제 DB에 Query를 날린다.
        &lt;ul&gt;
          &lt;li&gt;(영속성 전이가 되는 것처럼)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;컬렉션은 Member 소속의 단순한 값이기 때문에 Member에 모든 생명 주기를 맡긴다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;컬렉션 값&lt;/strong&gt; 타입 수정 예시2 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&amp;lt;Address&amp;gt;&lt;/code&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;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;============ START ============&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// old1 -&amp;gt; newCity1&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10001&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// equals 로 비교 &lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;newCity1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10001&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;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashCode()&lt;/code&gt; 에 대한 제대로 된 재정의가 필요하다.&lt;/li&gt;
      &lt;li&gt;AddressHistory 테이블에서 Member 에 소속된 Address 를 모두 지운다.
        &lt;ul&gt;
          &lt;li&gt;테이블에 있는 데이터를 갈아 끼운다.&lt;/li&gt;
          &lt;li&gt;old2, newCity1 에 대한 Address 를 새로 INSERT 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;아래 &lt;em&gt;제약사항 참고!&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;값-타입-컬렉션의-제약사항&quot;&gt;값 타입 컬렉션의 제약사항&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;값 타입 컬렉션은 값 타입은 엔티티와 다르게 식별자 개념이 없다.&lt;/li&gt;
  &lt;li&gt;값은 변경하면 추적이 어렵다.
    &lt;div class=&quot;language-sql 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;Hibernate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; 
      &lt;span class=&quot;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ADDRESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;MEMBER_ID&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bigint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;city&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;zipcode&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;ul&gt;
      &lt;li&gt;ADDRESS 에는 id가 존재하지 않는다.&lt;/li&gt;
      &lt;li&gt;그렇기 때문에 값이 중간에 변경되었을 때 DB가 해당 row만을 찾아서 변경할 수 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다. &lt;strong&gt;(중요!)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;대안
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@OrderColumn(name = &quot;address_history_order&quot;)&lt;/code&gt;를 사용하여 UPDATE Query가 날라갈 수 있도록 할 수 있다.&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;strong&gt;값 타입 컬렉션을 사용하지 말자.&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;대부분이 엔티티이다.&lt;/li&gt;
          &lt;li&gt;e.g. 주소&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; 그럼 값 타입 컬렉션은 언제 사용?
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 정말 단순한 경우! 추적할 필요도 없고 값이 바뀌어도 업데이트를 할 필요가 없을 때&lt;/li&gt;
          &lt;li&gt;e.g. select box 에서 [치킨, 피자, …] 중 여러 메뉴를 선택할 때&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 한다.
    &lt;ul&gt;
      &lt;li&gt;null 입력 X&lt;/li&gt;
      &lt;li&gt;중복 저장 X&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;값-타입-컬렉션-대안&quot;&gt;값 타입 컬렉션 대안&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;실무에서는 상황에 따라 값 타입 컬렉션 대신에 &lt;strong&gt;일대다 관계를 고려&lt;/strong&gt;하는 것이 낫다.
    &lt;ul&gt;
      &lt;li&gt;일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용하자.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬렉션처럼 사용하자.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;실무에서 쿼리 최적화에도 유리하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;대안에-대한-예시-코드&quot;&gt;대안에 대한 예시 코드&lt;/h4&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;nd&quot;&gt;@ElementCollection&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@CollectionTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FAVORITE_FOOD&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;joinColumns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FOOD_NAME&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&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;favoriteFoods&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;HashSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 변경 &lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@OneToMany&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cascade&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CascadeType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ALL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orphanRemoval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AddressEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressHistory&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;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&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;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;@Entity&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Getter&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Setter&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@NoArgsConstructor&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ADDRESS&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddressEntity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;homeCity&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;AddressEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10001&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAddressHistory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&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;AddressEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10002&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&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;ul&gt;
  &lt;li&gt;과정
    &lt;ul&gt;
      &lt;li&gt;Member 클래스에서 List&amp;lt;Address&amp;gt; 를 List&lt;AddressHistory&gt; 엔티티로 대체한다.
&lt;/AddressHistory&gt;        &lt;ul&gt;
          &lt;li&gt;@OneToMany와 @JoinColumn 으로 1:N 단방향 매핑을 한다.&lt;/li&gt;
          &lt;li&gt;영속성 전이(Cascade) + 고아 객체 제거&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;AddressEntity 클래스에서 내부적으로 Address 값 타입을 포함한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;개념
    &lt;ul&gt;
      &lt;li&gt;ADDRESS 테이블에 ID 라는 개념이 생겼다. 또한 MEMBER_ID를 FK로 가진다.
        &lt;ul&gt;
          &lt;li&gt;즉, 식별자가 있다는 것은 ADDRESS는 엔티티라는 것이고, 값을 가져와서 마음대로 수정할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;값 타입을 엔티티로 승급화&lt;/strong&gt;한다.
        &lt;ul&gt;
          &lt;li&gt;실제 실무에서 많이 사용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;c.f. 1:N 단방향에서 ADDRESS 테이블에 UPDATE Query가 나가는 것은 어쩔 수 없다.
        &lt;ul&gt;
          &lt;li&gt;Why? 다른 테이블 (Member)에 외래키가 있기 때문에&lt;/li&gt;
          &lt;li&gt;UPDATE Query를 없애려면 1:N, N:1 양방향으로 변경&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;정리&quot;&gt;정리&lt;/h2&gt;
&lt;ul&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;/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;
    &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;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 13 Sep 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/09/13/value-type-of-collection-copy.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/09/13/value-type-of-collection-copy.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>value-type</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 값 타입(1) - 기본값 타입, 임베디드 타입</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;기본값 타입&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;임베디드 타입 (복합 값 타입)&lt;/strong&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;strong&gt;값 타입 컬렉션&lt;/strong&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;jpa의-최상위-데이터-타입-분류-2가지&quot;&gt;JPA의 최상위 데이터 타입 분류 (2가지)&lt;/h1&gt;
&lt;h2 id=&quot;1-엔티티-타입&quot;&gt;1. 엔티티 타입&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;@Entity로 정의하는 객체&lt;/li&gt;
  &lt;li&gt;데이터가 변해도 식별자로 지속해서 추적이 가능하다.&lt;/li&gt;
  &lt;li&gt;e.g. 회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식이 가능하다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-값-타입&quot;&gt;2. 값 타입&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;int, Integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체&lt;/li&gt;
  &lt;li&gt;식별자가 없고 값만 있으므로 변경시 추적이 불가능하다.&lt;/li&gt;
  &lt;li&gt;e.g. 숫자 100을 200으로 변경하면 완전히 다른 값으로 대체된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;구체적인-데이터-타입-분류-3가지&quot;&gt;구체적인 데이터 타입 분류 (3가지)&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;기본값 타입
    &lt;ul&gt;
      &lt;li&gt;자바 기본 타입 (int, double)&lt;/li&gt;
      &lt;li&gt;래퍼 클래스 (Integer, Long)&lt;/li&gt;
      &lt;li&gt;String&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;임베디드 타입 (embedded type, 복합 값 타입)
    &lt;ul&gt;
      &lt;li&gt;JPA에서 정의해서 사용해야 한다.&lt;/li&gt;
      &lt;li&gt;e.g. 좌표의 경우, Position Class&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;컬렉션 값 타입 (collection value type)
    &lt;ul&gt;
      &lt;li&gt;마찬가지로 JPA에서 정의해서 사용해야 한다.&lt;/li&gt;
      &lt;li&gt;컬렉션에 기본값 또는 임베디드 타입을 넣은 형태이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1-기본값-타입&quot;&gt;1. 기본값 타입&lt;/h2&gt;
&lt;h3 id=&quot;종류&quot;&gt;종류&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;자바 기본 타입 (int, double)&lt;/li&gt;
  &lt;li&gt;래퍼 클래스 (Integer, Long)&lt;/li&gt;
  &lt;li&gt;String&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;특징&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;생명 주기를 엔티티에 의존한다.
    &lt;ul&gt;
      &lt;li&gt;e.g. 회원을 삭제하면 이름, 나이 필드도 함께 삭제된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;값 타입은 공유하면 안된다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Why?&lt;/strong&gt; Side Effect가 발생할 수 있기 때문에&lt;/li&gt;
      &lt;li&gt;e.g. 회원 이름 변경 시 다른 회원의 이름도 함께 변경되면 안된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;참고&quot;&gt;참고&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&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;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 20이라는 값을 복사&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;ul&gt;
      &lt;li&gt;int, double 같은 기본 타입(primitive type)은 절대 공유되지 않는다.&lt;/li&gt;
      &lt;li&gt;기본 타입은 공유되지 않고 항상 값을 복사한다.&lt;/li&gt;
      &lt;li&gt;즉, Side Effect가 발생하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Integer 같은 래퍼 클래스나 String과 같은 특수한 클래스는 공유 가능한 객체이지만 변경은 불가능하다.
    &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;Integer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// a의 참조를 복사 &lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Side Effect!! &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;10이 복사되는 것이 아니라 a의 레퍼런스가 넘어가서 같은 인스턴스를 공유한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.setValue(20)&lt;/code&gt; 에서 b값도 20으로 변경되는 Side Effect가 발생할 수 있다.&lt;/li&gt;
      &lt;li&gt;그래서! Java에서는 변경 자체를 불가능(Immutable)하게 만들어서 Side Effect를 막았다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;2-임베디드-타입-embedded-type-복합-값-타입&quot;&gt;2. 임베디드 타입 (embedded type, 복합 값 타입)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;새로운 값 타입을 직접 정의할 수 있다.&lt;/li&gt;
  &lt;li&gt;JPA는 &lt;strong&gt;임베디드 타입&lt;/strong&gt;(embedded type, 내장 타입)이라고 한다.&lt;/li&gt;
  &lt;li&gt;주로 기본 값 타입을 모아서 만들기 때문에 &lt;strong&gt;복합 값 타입&lt;/strong&gt;이라고도 한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예시&quot;&gt;예시&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;회원 엔티티는 이름, 근무 시작일, 근무 종료일, 주소 도시, 주소 번지, 주소 우편번호를 가진다.
  &lt;!-- - ![그림 추가]() --&gt;
    &lt;ul&gt;
      &lt;li&gt;startDate, endDate / city, street, zipcode 는 공통 필드로 사용 가능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;회원 엔티티는 이름, 근무기간, 집주소 가진다.
  &lt;!-- - ![그림 추가]() --&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;!-- - ![그림 추가]() --&gt;
    &lt;ul&gt;
      &lt;li&gt;클래스를 새로 뽑는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;특징-및-장점&quot;&gt;특징 및 장점&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;재사용이 가능하다.&lt;/li&gt;
  &lt;li&gt;클래스 내에서의 응집도가 높다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Period.isWork()&lt;/code&gt; 처럼 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있다.
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;객체지향적인 설계가 가능하다.&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;임베디드 타입도 int, String과 같은 값 타입이다. &lt;strong&gt;(중요!)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;엔티티가 아니다. 엔티티의 값일 뿐이다.&lt;/li&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;임베디드 타입의 값이 null 이라면 매핑한 컬럼 값은 모두 null로 저장된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;기본-사용법&quot;&gt;기본 사용법&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;기본 생성자&lt;/em&gt;는 필수이다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Embeddable&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;값 타입을 정의 하는 곳에 표시한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Embedded&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;값 타입을 사용하는 곳에 표시한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;c.f. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Embeddable&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Embedded&lt;/code&gt; 중 하나만 명시하면 되지만, 둘 다 적는 것을 권장한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;임베디드-타입과-테이블-매핑&quot;&gt;임베디드 타입과 테이블 매핑&lt;/h3&gt;
&lt;!-- - ![그림 추가]() --&gt;
&lt;ul&gt;
  &lt;li&gt;값 타입 / 임베디드 타입에 상관없이 &lt;strong&gt;DB&lt;/strong&gt; 회원 테이블의 형태는 동일하다.&lt;/li&gt;
  &lt;li&gt;하지만 &lt;strong&gt;객체&lt;/strong&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;homeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workAddress&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&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;@Embeddable&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@NoArgsConstructor&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zipcode&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;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Embeddable&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@NoArgsConstructor&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Period&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocalDateTime&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;startDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocalDateTime&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endDate&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;이점?
    &lt;ul&gt;
      &lt;li&gt;임베디드 타입을 사용하기 전과 후에 &lt;strong&gt;매핑하는 테이블은 같다.&lt;/strong&gt; (중요!)
        &lt;ul&gt;
          &lt;li&gt;임베디드 타입은 엔티티의 값일 뿐이다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;객체와 테이블을 아주 세밀하게(find-grained) 매핑하는 것이 가능하다.&lt;/li&gt;
      &lt;li&gt;잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다.&lt;/li&gt;
      &lt;li&gt;용어/코드를 공통으로 관리할 수 있게 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;임베디드-타입과-연관관계&quot;&gt;임베디드 타입과 연관관계&lt;/h3&gt;
&lt;!-- - ![그림 추가]() --&gt;
&lt;ul&gt;
  &lt;li&gt;임베디드 타입은 임베디드 타입을 가질 수 있다.
    &lt;ul&gt;
      &lt;li&gt;e.g. Address «Value» 임베디드 타입은 Zipcode «Value» 라는 임베디드 타입을 가진다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;임베디드 타입은 엔티티 타입을 가질 수 있다.
    &lt;ul&gt;
      &lt;li&gt;e.g. PhoneNumber «Value» 임베디드 타입이 PhoneEntity «Entity» 를 가질 수 있다.&lt;/li&gt;
      &lt;li&gt;FK만 가지면 되기 때문이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; 한 Entity 안에서 같은 값 타입을 2개 이상 가지면 어떻게 될까?
    &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;@Entity&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;homeAddress&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;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workAddress&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;o&quot;&gt;...&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;ul&gt;
      &lt;li&gt;컬럼 명이 중복된다.
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MappingException: Repeated column&lt;/code&gt; Error&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@AttributeOverrides&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@AttributeOverride&lt;/code&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;homeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Embedded&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@AttributeOverrides&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;nd&quot;&gt;@AttributeOverride&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WORK_CITY&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@AttributeOverride&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WORK_STREET&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@AttributeOverride&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;zipcode&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WORK_ZIPCODE&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)})&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;workAddress&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;값-타입과-불변-객체&quot;&gt;값 타입과 불변 객체&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;값 타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념이다.&lt;/li&gt;
  &lt;li&gt;따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;값-타입-공유-참조의-부작용&quot;&gt;값 타입 공유 참조의 부작용&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 굉장히 위험하다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Side Effect(부작용)&lt;/strong&gt;이 발생한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;예시
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Member Class가 같은 Address 객체를 가지고 있고, 두 Member 객체 중 첫 번째 Member의 Address(city) 속성만 변경하려고 하는 경우
        &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;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 첫 번째 member의 Address(city) 속성만 변경하고 싶다.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;new city&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// UPDATE Query 2번 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;결과
    &lt;ul&gt;
      &lt;li&gt;UPDATE Query가 두 번 날라간다.&lt;/li&gt;
      &lt;li&gt;즉, DB에서의 member1과 member2의 city 값이 모두 변경된다.&lt;/li&gt;
      &lt;li&gt;Side Effect와 같은 버그는 잡기가 굉장히 어렵다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;해결책
    &lt;ul&gt;
      &lt;li&gt;엔티티 간에 공유하고 싶은 값 타입은 &lt;strong&gt;엔티티로 만들어서 공유&lt;/strong&gt;해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;값-타입-복사&quot;&gt;값 타입 복사&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;위의 예시처럼 값 타입의 실제 인스턴스인 값을 공유하는 것은 굉장히 위험하다.&lt;/li&gt;
  &lt;li&gt;대신 값(인스턴스)를 복사해서 사용한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&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;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Address 객체 복사&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copyAddress&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStreet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getZipcode&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copyAddress&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;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 첫 번째 member의 Address(city) 속성만 변경된다.!&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;new city&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;객체-타입의-한계&quot;&gt;객체 타입의 한계&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;위의 예시처럼 항상 값을 복사해서 사용하면 공유 참조로 인해 발생하는 부작용을 피할 수 있다.&lt;/li&gt;
  &lt;li&gt;그러나, 임베디드 타입처럼 직접 정의한 값 타입은 자바의 기본 타입(primitive)이 아니라 객체 타입이다.
    &lt;ul&gt;
      &lt;li&gt;자바의 &lt;strong&gt;기본 타입&lt;/strong&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&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;/li&gt;
      &lt;li&gt;&lt;strong&gt;객체 타입&lt;/strong&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;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;old&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&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;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;new&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// a, b 모두 city가 변경된다.&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;li&gt;e.g. 누군가 실수로 복사하지 않은 address를 그대로 넣었다면 컴파일 단계에서 알 수 있는 방법이 없다. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member2.setHomeAddress(address)&lt;/code&gt;)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;따라서, &lt;strong&gt;객체의 공유 참조는 피할 수 없다.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;해결책
    &lt;ul&gt;
      &lt;li&gt;불변 객체 (Immutable Object)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;불변-객체-immutable-object&quot;&gt;불변 객체 (Immutable Object)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;값 타입은 불변 객체(immutable object)로 설계&lt;/strong&gt;해야 한다.
    &lt;ul&gt;
      &lt;li&gt;객체 타입을 수정할 수 없게 만들면 부작용(Side Effect)을 원천 차단할 수 있다.&lt;/li&gt;
      &lt;li&gt;불변이라는 작은 제약으로 부작용이라는 큰 재앙을 막을 수 있다&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;불변 객체&lt;/strong&gt;란
    &lt;ul&gt;
      &lt;li&gt;생성 시점 이후 절대 값을 변경할 수 없는 객체&lt;/li&gt;
      &lt;li&gt;생성자로만 값을 설정하고 Setter를 만들지 않으면 된다.&lt;/li&gt;
      &lt;li&gt;c.f. Integer, String은 자바가 제공하는 대표적인 불변 객체이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; 원래 값 객체의 필드를 실제로 바꾸고 싶으면?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; Address 를 통으로 변경해야 한다.
    &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;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;street&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;10000&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
  &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
  &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAddress&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;Address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NewCity&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStreet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getZipcode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHomeAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newAddress&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;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&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;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;값-타입의-비교&quot;&gt;값 타입의 비교&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&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;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;a == b: &quot;&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;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;객체 타입은 값이 같아도 주소가 다르기 때문에 == 비교 시 false를 반환한다.
    &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;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address1&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;Address&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;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address2&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;Address&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;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;address1 == address2: &quot;&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;address1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;동일성(identity)&lt;/strong&gt; 비교
    &lt;ul&gt;
      &lt;li&gt;인스턴스의 참조 값을 비교한다.&lt;/li&gt;
      &lt;li&gt;== 사용&lt;/li&gt;
      &lt;li&gt;primitive 타입&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;동등성(equivalence)&lt;/strong&gt; 비교
    &lt;ul&gt;
      &lt;li&gt;인스턴스의 값을 비교한다.&lt;/li&gt;
      &lt;li&gt;equals() 사용&lt;/li&gt;
      &lt;li&gt;임베디드 타입&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.out.println(&quot;address1 == address2: &quot; + (address1.equals(address2)));&lt;/code&gt; // 재정의 시 true&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;값 타입은 a.equals(b)를 사용해서 동등성 비교를 해야 한다.&lt;/li&gt;
  &lt;li&gt;값 타입의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals()&lt;/code&gt; 메소드를 적절하게 재정의해야 한다.
    &lt;ul&gt;
      &lt;li&gt;자동으로 만들어주는 equals()를 이용한다.&lt;/li&gt;
      &lt;li&gt;(주로 모든 필드를 사용하여 재정의 한다.)&lt;/li&gt;
      &lt;li&gt;equals()에 맞게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashCode()&lt;/code&gt;도 재정의 해줘야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2019/09/13/value-type-of-collection-copy.html&quot;&gt;컬렉션 타입 참고 POST&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Thu, 12 Sep 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/09/12/value-type-of-basic-and-embedded.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/09/12/value-type-of-basic-and-embedded.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>value-type</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 양방향 연관관계란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h1 id=&quot;양방향-연관관계와-연관관계의-주인&quot;&gt;양방향 연관관계와 연관관계의 주인&lt;/h1&gt;
&lt;!-- ## Goal
&gt; - --&gt;

&lt;h2 id=&quot;양방향-연관관계&quot;&gt;양방향 연관관계&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;연관관계를 찾는 방법
    &lt;ul&gt;
      &lt;li&gt;객체는 참조, DB는 외래 키를 이용한 JOIN&lt;/li&gt;
      &lt;li&gt;이 둘 간의 차이를 이해해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;테이블 연관관계는 단방향 연관관계에서와 동일하다.
    &lt;ul&gt;
      &lt;li&gt;Why?
        &lt;ul&gt;
          &lt;li&gt;Member에서 Team을 알고 싶으면 TEAM_ID인 FK로 JOIN을 하면 된다.&lt;/li&gt;
          &lt;li&gt;Team에서 Member를 알고 싶으면 마찬가지로 나의 PK로 JOIN을 하면 된다.&lt;/li&gt;
          &lt;li&gt;즉, 테이블의 연관관계는 사실상 방향이 없다. (FK로 서로를 알 수 있기 때문)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;객체에서의 연관관계를 위해서는 Team에서도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List members&lt;/code&gt; 가 필요하다.
    &lt;ul&gt;
      &lt;li&gt;즉, 객체 설계에서 양방향을 구현하고 싶으면 Member에서는 Team을 가지고 있고, Team에서는 List Members를 가지고 있도록 설계하면 된다.&lt;/li&gt;
      &lt;li&gt;이렇게 하면 Team에서도 getMemberList()로 특정 팀에 속한 멤버 리스트를 가져올 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예제&quot;&gt;예제&lt;/h3&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;USERNAME&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@ManyToOne&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// N:1&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TEAM_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TEAM_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@OneToMany&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappedBy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;team&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1:N&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;members&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;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 초기화 (관례) - NullPointerException 방지 &lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&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;ul&gt;
  &lt;li&gt;Member —N:1— Team
    &lt;ul&gt;
      &lt;li&gt;Member 입장에서는 다대일, Team 입장에서는 일대다의 관계를 갖는다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Member 엔티티&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;단방향과 동일하다.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ManyToOne&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Team 엔티티&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;Member 컬렉션을 추가한다.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@OneToMany(mappedBy = &quot;team&quot;)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;mappedBy로 team과 연관이 있는 것을 알려준다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&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;c1&quot;&gt;// Member 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// team에서 멤버들 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;members&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMembers&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;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;연관관계-주인과-mappedby&quot;&gt;연관관계 주인과 mappedBy&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;mappedBy
    &lt;ul&gt;
      &lt;li&gt;JPA의 멘탈붕괴 난이도&lt;/li&gt;
      &lt;li&gt;처음에는 이해하기 어렵지만, &lt;strong&gt;객체와 테이블간에 연관관계를 맺는 차이&lt;/strong&gt;를 이해하면 쉬워진다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;객체는 방향을 가지고 있고, DB는 방향성이 없다.
    &lt;ul&gt;
      &lt;li&gt;DB 테이블에서는 FK 하나로 양방향 관계(서로 JOIN)를 맺을 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;객체와-테이블간에-연관관계를-맺는-차이&quot;&gt;객체와 테이블간에 연관관계를 맺는 차이&lt;/h3&gt;
&lt;h4 id=&quot;객체-연관관계--2개&quot;&gt;객체 연관관계 = 2개&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;회원 -&amp;gt; 팀 연관관계 1개 (단방향)&lt;/li&gt;
  &lt;li&gt;팀 -&amp;gt; 회원 연관관계 1개 (단방향)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;객체의 양방향 관계&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개이다.&lt;/li&gt;
      &lt;li&gt;객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 한다.
        &lt;ul&gt;
          &lt;li&gt;A -&amp;gt; B(a.getB())
            &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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;/li&gt;
          &lt;li&gt;B -&amp;gt; A(b.getA())
            &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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;테이블-연관관계--1개&quot;&gt;테이블 연관관계 = 1개&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;회원 &amp;lt;-&amp;gt; 팀의 연관관계 1개 (양방향, 사실 방향이 없음)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;테이블의 양방향 연관관계&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다.&lt;/li&gt;
      &lt;li&gt;MEMBER.TEAM_ID 외래 키(FK) 하나로 양방향 연관관계를 가진다. (양쪽에서 서로 JOIN 가능)
        &lt;div class=&quot;language-sql 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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MEMBER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TEAM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt; &lt;span class=&quot;o&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;TEAM_ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
        &lt;div class=&quot;language-sql 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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TEAM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MEMBER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&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;TEAM_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;둘-중-하나로-외래-키를-관리해야-한다&quot;&gt;둘 중 하나로 외래 키를 관리해야 한다&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;객체에서의 양방향 관계
    &lt;ul&gt;
      &lt;li&gt;Member도 Team을 가지고, Team도 Member를 가지면 이제 둘 중에 뭘로 연관관계를 매핑해야 할까?&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;Member의 team 값을 업데이트 했을 때, Member의 TEAM_ID(FK)를 업데이트?&lt;/li&gt;
          &lt;li&gt;아니면 Team의 members 값을 업데이트 했을 때, Member의 TEAM_ID(FK)를 업데이트?&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;팀에 멤버를 바꾸고 싶거나 새로운 팀으로 들어가고 싶을 때,&lt;/li&gt;
          &lt;li&gt;Member의 team 값을 업데이트? 아니면 Team의 members 값을 업데이트?&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;DB에서는 객체가 참조를 어떻게 하든 외래 키값(Member의 TEAM_ID)만 업데이트하면 된다.&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;strong&gt;연관관계의 주인&lt;/strong&gt;이라는 개념이 나왔다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;연관관계의-주인owner&quot;&gt;연관관계의 주인(Owner)&lt;/h3&gt;
&lt;h4 id=&quot;양방향-매핑-규칙&quot;&gt;양방향 매핑 규칙&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;객체의 두 관계 중 하나를 연관관계의 주인으로 지정한다.&lt;/li&gt;
  &lt;li&gt;연관관계의 주인만이 외래 키를 관리한다.
    &lt;ul&gt;
      &lt;li&gt;진짜 매핑&lt;/li&gt;
      &lt;li&gt;주인만이 DB에 접근하여 값을 등록, 수정, 변경할 수 있다.&lt;/li&gt;
      &lt;li&gt;주인이 아닌 객체가 값을 변경하더라도 DB에는 영향이 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;주인이 아닌쪽은 읽기(SELECT)만 가능&lt;/strong&gt;하다.
    &lt;ul&gt;
      &lt;li&gt;가짜 매핑&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;누구를-주인으로-해야-할까&quot;&gt;누구를 주인으로 해야 할까?&lt;/h4&gt;
&lt;!-- 색 추가 --&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;외래 키가 있는 곳을 주인으로 정해라.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;DB에서는 N에 해당하는 테이블이 FK를 가지고 있다. (N쪽이 연관관계의 주인)&lt;/li&gt;
      &lt;li&gt;즉, @JoinColumn이 있는 쪽이 주인이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;N:1 의 관계에서 N에 해당하는 쪽(FK를 가짐)이 연관관계의 주인이 된다.
    &lt;ul&gt;
      &lt;li&gt;여기서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Member.team&lt;/code&gt;이 연관관계의 주인이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;연관관계의 주인은 비즈니스 적으로 중요하지 않다.
    &lt;ul&gt;
      &lt;li&gt;단지 FK를 가진 N쪽이 주인이 된다.&lt;/li&gt;
      &lt;li&gt;Ex. [자동차 —1:N— 바퀴] 에서는 바퀴가 연관관계의 주인이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이렇게 해야 성능 이슈도 없고 설계도 깔끔한 구조가 된다.
    &lt;ul&gt;
      &lt;li&gt;깔끔한 구조
        &lt;ul&gt;
          &lt;li&gt;엔티티 하나에서 관리가 된다.&lt;/li&gt;
          &lt;li&gt;즉, FK가 있는 엔티티에서 연관관계도 관리할 수 있다.&lt;/li&gt;
          &lt;li&gt;Ex. Member의 team을 바꿨더니 Member의 UPDATE Query가 날라간다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Team.members&lt;/code&gt;를 주인으로 선택하고 Team의 List members를 변경했다. 그 결과는?
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 다른 테이블인 Member의 UPDATE Query가 날라간다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;주인인-객체와-주인이-아닌-객체의-구현-방법&quot;&gt;주인인 객체와 주인이 아닌 객체의 구현 방법&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Member —N:1— Team
    &lt;ul&gt;
      &lt;li&gt;Member 입장에서는 다대일, Team 입장에서는 일대다의 관계를 갖는다.&lt;/li&gt;
      &lt;li&gt;Member가 Owner가 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;주인인 객체&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;mappedBy 속성을 사용하지 않는다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ManyToOne&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@JoinColumn&lt;/code&gt; 필요&lt;/li&gt;
      &lt;li&gt;mappedBy의 뜻?
        &lt;ul&gt;
          &lt;li&gt;어떤 대상에 의해서 매핑이 되었다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;주인이 아닌 객체&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;mappedBy 속성으로 주인을 지정한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@OneToMany&lt;/code&gt; 필요&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- 
    - 엔티티랑 테이블이 매핑이 되어있는 테이블에서 FK가 관리가 된다.
- 모 민족에서 프로젝트 중에, 모두 단방향으로 설계하고 개발했다. 양방향으로 뚫어서 조회가 필요한 경우에 그 때 양방향 매핑 하면 된다. 자바 코드만 수정이 일어나기 때문에 DB에 영향 주지 않는다.
  - 이미, 단방향 매핑만으로 ORM 매핑이 다 끝났다. 양방향은 단순히 조회를 편하게 하기 위해 부가 기능이 조금더 들어가는 거라고 보면 된다. 어차피 조회할 수 있는 기능만 있다.
 --&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Wed, 14 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/14/bidirectional-association.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/14/bidirectional-association.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>entity-mapping</category>
        
        <category>bidirectional-association</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 단방향 연관관계란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h1 id=&quot;단방향-연관관계&quot;&gt;단방향 연관관계&lt;/h1&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;객체와 테이블 연관관계의 차이를 이해한다.&lt;/li&gt;
    &lt;li&gt;객체의 참조와 테이블의 외래 키를 어떻게 매핑하는지 안다.&lt;/li&gt;
    &lt;li&gt;용어 이해
      &lt;ul&gt;
        &lt;li&gt;방향 (Direction)
          &lt;ul&gt;
            &lt;li&gt;단방향, 양방향&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;다중성 (Multiplicity)
          &lt;ul&gt;
            &lt;li&gt;다대일 (N:1), 일대다 (1:N), 일대일 (1:1), 다대다 (N:N)&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;
        &lt;li&gt;연관관계의 주인 (Owner)
          &lt;ul&gt;
            &lt;li&gt;객체 양방향 연관관계는 관리하는 주인이 필요하다.&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;연관관계가-필요한-이유&quot;&gt;연관관계가 필요한 이유&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;‘객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다’ - 조영호(객체지향의 사실과 오해)&lt;/li&gt;
  &lt;li&gt;객체를 테이블에 맞추어 모델링 -&amp;gt; 객체 지향 모델링 (객체 연관관계 사용)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예제-시나리오&quot;&gt;예제 시나리오&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;회원과 팀이 있다.&lt;/li&gt;
  &lt;li&gt;회원은 하나의 팀에만 소속될 수 있다.&lt;/li&gt;
  &lt;li&gt;회원과 팀은 다대일 관계다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-객체를-테이블에-맞추어-모델링-연관-관계가-없는-객체&quot;&gt;1. 객체를 테이블에 맞추어 모델링 (연관 관계가 없는 객체)&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;N:1의 연관관계를 가지는 테이블
    &lt;ul&gt;
      &lt;li&gt;Member —N:1— Team&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;연관관계가 없는 객체
    &lt;ul&gt;
      &lt;li&gt;참조 대신 외래 키(teamId)를 그대로 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;USERNAME&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TEAM_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;teamId&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;q-객체를-테이블에-맞추어-모델링-했을-때의-문제점&quot;&gt;Q. 객체를 테이블에 맞추어 모델링 했을 때의 문제점?&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;저장&lt;/strong&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;c1&quot;&gt;// 팀 저장&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;Team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TeamA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;	&lt;span class=&quot;c1&quot;&gt;// PK값이 세팅된 상태 (영속 상태)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 회원 저장&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Memeber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTeamId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;ul&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 외래 키의 식별자를 직접 다뤄야 하는 문제가 있다.
        &lt;ul&gt;
          &lt;li&gt;Team 객체를 영속화한 후 Member의 teamId값(FK)에 직접 값을 세팅해줘야 한다.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.setTeamId(team.getId();&lt;/code&gt;은 위에서 team이 영속 상태 이므로 getId()해서 가져올 수 있지만, 객체 지향적인 방법이 아니다.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.setTeam(team);&lt;/code&gt;과 같이 사용하고 싶다는 생각이 들 것이다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;조회&lt;/strong&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;c1&quot;&gt;// 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findTeam&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;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;c1&quot;&gt;// 먼저 식별자를 가져와야 함 (가져옴)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findTeamId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeamId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findTeam&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;ul&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 연관 관계가 없기 때문에 식별자를 통해 다시 팀을 조회해야 한다.&lt;/li&gt;
      &lt;li&gt;즉, 조회를 두 번 해야 한다.&lt;/li&gt;
      &lt;li&gt;객체 지향적인 방법은 아니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;결론&lt;/strong&gt;
    &lt;ul&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;li&gt;테이블과 객체 사이에는 이런 큰 간격이 존재한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;단방향-연관관계-매핑-이론&quot;&gt;단방향 연관관계 매핑 이론&lt;/h2&gt;
&lt;h3 id=&quot;2-객체-지향-모델링-객체-연관관계-사용&quot;&gt;2. 객체 지향 모델링 (객체 연관관계 사용)&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;N:1의 연관관계를 가지는 테이블
    &lt;ul&gt;
      &lt;li&gt;Member —N:1— Team&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;객체 연관관계 사용
    &lt;ul&gt;
      &lt;li&gt;객체의 참조와 테이블의 외래 키를 매핑한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@Entity&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_ID&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;USERNAME&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
&lt;span class=&quot;c1&quot;&gt;//  @Column(name = &quot;TEAM_ID&quot;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//  private Long teamId;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@ManyToOne&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;TEAM_ID&quot;&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;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;외래 키 대신에 Team 객체를 넣고 TEAM_ID를 매핑한다.&lt;/li&gt;
  &lt;li&gt;조인할 컬럼을 명시한다.
    &lt;ul&gt;
      &lt;li&gt;@JoinColumn으로 조인 컬럼을 명시한다.&lt;/li&gt;
      &lt;li&gt;안적어도 default로 들어가지만, 적어 주는 것이 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;연관관계를 맺는다.
    &lt;ul&gt;
      &lt;li&gt;Member —N:1— Team&lt;/li&gt;
      &lt;li&gt;Member 입장에서는 다대일, Team 입장에서는 일대다의 관계를 갖는다.&lt;/li&gt;
      &lt;li&gt;@ManyToOne으로 연관관계를 설정한다.&lt;/li&gt;
      &lt;li&gt;Team 이라는 필드가 DB의 “TEAM_ID”라는 외래 키와 매핑된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;orm-매핑&quot;&gt;ORM 매핑&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;객체의 참조와 테이블의 외래 키를 매핑하여 단방향 연관관계를 설정한다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;저장&lt;/strong&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;c1&quot;&gt;// 팀 저장&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;Team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TeamA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Memeber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&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;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;ul&gt;
      &lt;li&gt;Team 객체를 그대로 넣는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;조회&lt;/strong&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;c1&quot;&gt;// 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&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;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findTeam&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&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;div class=&quot;language-sql 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;k&quot;&gt;select&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEMBER_ID&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;USERNAME&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;team&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;k&quot;&gt;from&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;outer&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;join&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MEMBER_ID&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;ul&gt;
      &lt;li&gt;Member의 getTeam()을 통해 연관된 Team을 바로 조회할 수 있다.
        &lt;ul&gt;
          &lt;li&gt;참조로 연관관계를 조회할 수 있다. 
&lt;!-- - 객체 그래프 탐색!! --&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;위의 SELECT Query문을 보면
        &lt;ul&gt;
          &lt;li&gt;JPA가 조인을 통해 Member와 Team을 한 번에 가지고 오는 것을 확인할 수 있다.&lt;/li&gt;
          &lt;li&gt;하지만, 처음부터 조인해서 가져오지 않고 일단 멤버만 가져오고 싶다라고 하면&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;fetchtype-옵션&quot;&gt;FetchType 옵션&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@ManyToOne(fetch = FetchType.LAZY)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;지연 로딩 전략&lt;/li&gt;
      &lt;li&gt;실제 연관관계를 가진 팀이 Touch 될 때, 그 때 Team을 조회하는 쿼리를 날려서 가져온다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@ManyToOne(fetch = FetchType.EAGER)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;기본값&lt;/li&gt;
      &lt;li&gt;연관관계를 가진 객체를 조인해서 먼저 모두 가져온다.
&lt;!-- - 현업에서는 전부 다 LAZY로 기본 설정 해놓고, 꼭 필요한 경우에만 쿼리를 실제 날리는 시점에 원하는 결과를 최적화해서 가져오는 방법을 사용하는 것을 권장한다. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;[참고]&lt;/strong&gt; 영속성 1차 캐시에서 가져오지 않고 DB Query를 날려서 직접 확인하고 싶으면,&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;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 현재 영속성 컨텍스트에 있는 것을 DB에 던져서 sync를 맞춘다.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// find 시 날라가는 쿼리를 확인한다.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clear()&lt;/code&gt;가 없으면 아래의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find()&lt;/code&gt;에서는 SELECT Query는 날라가지 않는다.&lt;/li&gt;
  &lt;li&gt;영속성 컨텍스트의 1차 캐시에 쿼당 객체를 저장하기 때문에 쿼리를 날리지 않고 1차 캐시에서 객체 정보를 가져오기 때문이다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;연관관계-수정&quot;&gt;연관관계 수정&lt;/h3&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;c1&quot;&gt;// 새로운 팀B&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;teamB&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;Team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;teamB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;TeamB&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;teamB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 회원1에 새로운 팀B 설정&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;teamB&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;ul&gt;
  &lt;li&gt;setTeam()을 통해 기존의 팀을 새로운 팀으로 변경하면, 연관관계가 바뀐다.&lt;/li&gt;
  &lt;li&gt;UPDATE Query를 통해서 FK 가 업데이트된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 13 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/13/one-way-association.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/13/one-way-association.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>entity-mapping</category>
        
        <category>one-way-association</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 기본키(PK) 매핑 방법 및 생성 전략</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;기본 키 매핑 방법&lt;/li&gt;
    &lt;li&gt;기본 키 자동 생성 전략 4가지
      &lt;ul&gt;
        &lt;li&gt;IDENTITY&lt;/li&gt;
        &lt;li&gt;SEQUENCE&lt;/li&gt;
        &lt;li&gt;TABLE&lt;/li&gt;
        &lt;li&gt;AUTO&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;기본 키 생성 전략&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;기본-키-매핑&quot;&gt;기본 키 매핑&lt;/h2&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;@Id&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenerationType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AUTO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&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;ol&gt;
  &lt;li&gt;직접 할당
    &lt;ul&gt;
      &lt;li&gt;@Id 만 사용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자동 생성
    &lt;ul&gt;
      &lt;li&gt;@Id와 @GeneratedValue를 같이 사용&lt;/li&gt;
      &lt;li&gt;네 가지 전략이 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;자동-생성-전략-네-가지&quot;&gt;자동 생성 전략 (네 가지)&lt;/h2&gt;
&lt;h3 id=&quot;identity&quot;&gt;IDENTITY&lt;/h3&gt;
&lt;h4 id=&quot;개념&quot;&gt;개념&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GeneratedValue(strategy = GenerationType.IDENTITY)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;기본 키 생성을 데이터베이스에 위임&lt;/li&gt;
  &lt;li&gt;즉, id 값을 null로 하면 DB가 알아서 &lt;strong&gt;AUTO_INCREMENT&lt;/strong&gt; 해준다.
    &lt;ul&gt;
      &lt;li&gt;Ex) MySQL, PostgreSQL, SQL Server DB2 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenerationType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IDENTITY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;div class=&quot;language-sql 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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;H2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;generated&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;identity&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MySQL&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auto_increment&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;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;특징&quot;&gt;특징&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;IDENTITY 전략은 entityManager.persist() 시점에 즉시 INSERT SQL을 실행하고 DB에서 식별자를 조회한다.
    &lt;ul&gt;
      &lt;li&gt;JPA는 보통 트랜잭션 commit 시점에 INSERT SQL을 실행한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;[추가 설명]&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;IDENTITY 전략은 id 값을 설정하지 않고(null) INSERT Query를 날리면 그때 id의 값을 세팅한다.
            &lt;ul&gt;
              &lt;li&gt;AUTO_INCREMENT는 DB에 INSERT SQL을 실행한 이후에 id 값을 알 수 있다.&lt;/li&gt;
              &lt;li&gt;즉, id 값은 DB에 값이 들어간 이후에서야 알 수 있다는 것이다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; id 값을 DB에 값이 들어간 이후에 알게 됐을 때의 문제점?
            &lt;ul&gt;
              &lt;li&gt;영속성 컨텍스트에서 해당 객체가 관리되려면 무조건 pk 값이 있어야 한다.&lt;/li&gt;
              &lt;li&gt;하지만 이 경우 pk 값은 DB에 들어가봐야 알 수가 있다.&lt;/li&gt;
              &lt;li&gt;다시 말해서, IDENTITY 전략의 경우 영속성 컨텍스트의 1차 캐시 안에 있는 @Id 값은 DB에 넣기 전까지는 세팅을 할 수 없다는 것이다. (JPA 입장에서는 Map의 key 값이 없으니까 해당 객체의 값을 넣을 수 있는 방법이 없다.)&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 해결책?
            &lt;ul&gt;
              &lt;li&gt;&lt;strong&gt;&lt;em&gt;IDENTITY 전략에서만 예외적으로&lt;/em&gt;&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.persist()&lt;/code&gt;가 호출되는 시점에 바로 DB에 INSERT 쿼리를 날린다. (다른 전략에서는 이미 id 값을 알고 있기 때문에 commit 하는 시점에 INSERT 쿼리를 날린다.)&lt;/li&gt;
              &lt;li&gt;위의 과정을 통해 entityManager.persist()가 호출되자마자 INSERT SQL을 통해 DB에서 식별자를 조회하여 영속성 컨텍스트의 1차 캐시에 값을 넣는다. (SELECT 문을 다시 날리지 않아도 된다.)&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;단점: 모아서 INSERT 하는 것이 불가능하다.
    &lt;ul&gt;
      &lt;li&gt;하지만, 버퍼링해서 Write 하는 것이 큰 이득이 있지 않기 때문에 크게 신경쓰지 않아도 된다.&lt;/li&gt;
      &lt;li&gt;하나의 Transaction 안에서 여러 INSERT Query가 네트워크를 탄다고 해서 엄청나게 비약적인 차이가 나지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sequence&quot;&gt;SEQUENCE&lt;/h3&gt;
&lt;h4 id=&quot;개념-1&quot;&gt;개념&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GeneratedValue(strategy = GenerationType.SEQUNCE)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;데이터베이스 &lt;strong&gt;Sequence Object&lt;/strong&gt;를 사용
    &lt;ul&gt;
      &lt;li&gt;DB Sequence는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트&lt;/li&gt;
      &lt;li&gt;테이블 마다 시퀀스 오브젝트를 따로 관리하고 싶으면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@SequenceGenerator&lt;/code&gt;에 sequenceName 속성을 추가한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;즉, DB가 자동으로 숫자를 generate 해준다.
    &lt;ul&gt;
      &lt;li&gt;Ex) Oracle, PostgreSQL, DB2, H2 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@SequenceGenerator&lt;/code&gt; 필요&lt;/li&gt;
&lt;/ul&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;@Entity&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@SequenceGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ_GENERATOR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;n&quot;&gt;sequenceName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ&quot;&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;n&quot;&gt;initialValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;allocationSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenerationType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SEQUENCE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ_GENERATOR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;div class=&quot;language-sql 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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;부터&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;시작해서&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;씩&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;증가&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sequence&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MEMBER_SEQ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;increment&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;특징-1&quot;&gt;특징&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;SEQUENCE 전략은 id 값을 설정하지 않고(null) generator에 매핑된 Sequence 전략(“MEMBER_SEQ”)에서 id 값을 얻어온다.
    &lt;ul&gt;
      &lt;li&gt;해당 Sequence Object는 DB가 관리하는 것이기 때문에 DB에서 id 값을 가져와야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q1.&lt;/strong&gt; id 값을 DB에 값이 들어간 이후에 알게 됐을 때의 문제점?
    &lt;ul&gt;
      &lt;li&gt;위의 IDENTITY 전략과 마찬가지의 상태&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A1.&lt;/strong&gt; 해결책?
    &lt;ul&gt;
      &lt;li&gt;1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.persist()&lt;/code&gt;를 호출하기 전에 DB의 Sequence에서 pk 값을 가져와야 한다.
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate: call next value for MEMBER_SEQ&lt;/code&gt;이 수행됨.&lt;/li&gt;
          &lt;li&gt;현재의 값: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.id = 1&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;2) DB에서 가져온 pk 값을 해당 객체의 id 에 넣는다.&lt;/li&gt;
      &lt;li&gt;3) 이후에 entityManager.persist()를 통해 영속성 컨텍스트에 해당 객체가 저장되는 것이다.
        &lt;ul&gt;
          &lt;li&gt;이 상태에서는 아직 DB에 INSERT 쿼리가 날라가지 않고, 영속성 컨텍스트에 쌓여있다가 트랜잭션 commit 하는 시점에 INSERT 쿼리가 날라간다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;4) 필요한 경우 버퍼링이 가능하다.
        &lt;ul&gt;
          &lt;li&gt;IDENTITY 전략에서는 INSERT 쿼리를 날려야 pk를 알 수 있었기 때문에 버퍼링이 불가능하다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q2.&lt;/strong&gt; 위의 해결책이면 계속 네트워크를 왔다갔다 해야되기 때문에 성능 상의 저하가 있지 않을까?
    &lt;ul&gt;
      &lt;li&gt;SEQUENCE 전략을 사용할 경우, Sequence를 매번 DB에서 가지고오는 과정에서 네트워크를 타기 때문에 성능 상의 저하를 가져올 수 있다.&lt;/li&gt;
      &lt;li&gt;차라리 INSERT Query를 한 번에 날리는 것이 낫지 않을까?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A2.&lt;/strong&gt; allocationSize 속성값 (기본값: 50) 이용
    &lt;ul&gt;
      &lt;li&gt;이를 해결하기 위한 성능 최적화의 방법으로 allocationSize 옵션을 사용한다.&lt;/li&gt;
      &lt;li&gt;1) 이 옵션을 사용하면 next call을 할 때 미리 DB에 50개를 한 번에 올려 놓고 (DB는 sequence가 51로 세팅된다.) 메모리 상에서 1개씩 쓰는 것이다.&lt;/li&gt;
      &lt;li&gt;2) 50개를 모두 사용하면 그 때 또 next call을 날려서 다시 50개를 올려 놓는다. (DB는 sequence가 101로 세팅된다.) 메모리에서 sequence를 가져와 51부터 사용할 수 있다.
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create sequence MEMBER_SEQ start with 1 increment by 50&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&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;c1&quot;&gt;// 1(1로 맞추기 위한 dummy 호출), 51(최적화를 위한 호출)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// next call 2번 호출 &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// MEM&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// MEM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q3.&lt;/strong&gt; 옵션값을 50보다 큰 수로 정하면 좋지 않나?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A3.&lt;/strong&gt; 이론적으로는 더 큰 수로 설정할수록 성능은 좋아진다.
    &lt;ul&gt;
      &lt;li&gt;하지만, 중간에 애플리케이션(웹 서버)를 내리는 시점에 사용하지 않는 seq 값이 날라간다. 즉, 중간에 구멍이 생긴다.&lt;/li&gt;
      &lt;li&gt;중간의 seq 공백이 큰 문제가 되는 것은 아니지만, 그래도 낭비가 되는 것이므로 적당한 50~100 사이로 설정하는 것이 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;sequencegenerator-속성&quot;&gt;@SequenceGenerator 속성&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;속성&lt;/th&gt;
      &lt;th&gt;설명&lt;/th&gt;
      &lt;th&gt;기본값&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;name&lt;/td&gt;
      &lt;td&gt;식별자 생성기 이름&lt;/td&gt;
      &lt;td&gt;필수&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sequenceName&lt;/td&gt;
      &lt;td&gt;데이터베이스에 등록되어 있는 시퀀스 이름&lt;/td&gt;
      &lt;td&gt;hibernate_sequence&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;initialValue&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정한다.&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;allocationSize&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용), &lt;strong&gt;데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다.&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;50&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;catalog, schema&lt;/td&gt;
      &lt;td&gt;데이터베이스 catalog, schema 이름&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;table&quot;&gt;TABLE&lt;/h3&gt;
&lt;h4 id=&quot;개념-2&quot;&gt;개념&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GeneratedValue(strategy = GenerationType.TABLE)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@TableGenerator&lt;/code&gt; 필요&lt;/li&gt;
&lt;/ul&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;@Entity&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@SequenceGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ_GENERATOR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MY_SEQUENCES&quot;&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;n&quot;&gt;pkColumnValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;allocationSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenerationType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TABLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MEMBER_SEQ_GENERATOR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;div class=&quot;language-sql 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;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_SEQUENCES&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sequence_name&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;next_val&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bigint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;primaty&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sequence_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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;특징-2&quot;&gt;특징&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;장점: 모든 데이터베이스에 적용 가능&lt;/li&gt;
  &lt;li&gt;단점: 최적화 되어있지 않은 테이블을 직접 사용하기 때문에 성능상의 이슈가 있음&lt;/li&gt;
  &lt;li&gt;운영 서버에서는 사용하기에 적합하지 않다.
    &lt;ul&gt;
      &lt;li&gt;Why? DB에서 관례로 쓰는 것이 있기 때문에&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; Table 전략에서 allocationSize = 50이고, 서버가 여러 대인 경우에는 문제가 없을까?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; 문제 없다.
    &lt;ul&gt;
      &lt;li&gt;미리 값을 올려두는 방식이기 때문에 여러 대의 서버가 붙더라도 상관이 없다.&lt;/li&gt;
      &lt;li&gt;웹 서버 10대가 동시에 호출하는 경우, 순차적으로 사용하여 값이 올라가 있을 것이다.
        &lt;ul&gt;
          &lt;li&gt;A 서버: 1~50&lt;/li&gt;
          &lt;li&gt;B 서버: 51~100 …&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tablegenerator-속성&quot;&gt;@TableGenerator 속성&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;속성&lt;/th&gt;
      &lt;th&gt;설명&lt;/th&gt;
      &lt;th&gt;기본값&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;name&lt;/td&gt;
      &lt;td&gt;식별자 생성기 이름&lt;/td&gt;
      &lt;td&gt;필수&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;table&lt;/td&gt;
      &lt;td&gt;키 생성 테이블 명&lt;/td&gt;
      &lt;td&gt;hibernate_sequences&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pkColumnName&lt;/td&gt;
      &lt;td&gt;시퀀스 컬럼명&lt;/td&gt;
      &lt;td&gt;sequence_name&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;valueColumnNa&lt;/td&gt;
      &lt;td&gt;시퀀스 값 컬럼명&lt;/td&gt;
      &lt;td&gt;next_val&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pkColumnValue&lt;/td&gt;
      &lt;td&gt;키로 사용할 값 이름&lt;/td&gt;
      &lt;td&gt;엔티티 이름&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;initialValue&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;초기 값, 마지막으로 생성된 값이 기준&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;allocationSize&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용)&lt;/td&gt;
      &lt;td&gt;50&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;catalog, schema&lt;/td&gt;
      &lt;td&gt;데이터베이스 catalog, schema 이름&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;uniqueConstraints(DDL)&lt;/td&gt;
      &lt;td&gt;유니크 제약 조건을 지정할 수 있다.&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;auto&quot;&gt;AUTO&lt;/h3&gt;
&lt;h4 id=&quot;개념-3&quot;&gt;개념&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@GeneratedValue(strategy = GenerationType.AUTO)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;기본 설정 값&lt;/li&gt;
  &lt;li&gt;방언에 따라 위의 세 가지 전략을 자동으로 지정한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;권장하는-식별자-전략&quot;&gt;권장하는 식별자 전략&lt;/h2&gt;
&lt;h3 id=&quot;기본-키-제약-조건&quot;&gt;기본 키 제약 조건&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;null이 아니다.&lt;/li&gt;
  &lt;li&gt;유일하다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;변하면 안된다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 그 대신 대리키/대체키를 사용하자.
    &lt;ul&gt;
      &lt;li&gt;자연키 (Natural Key)
        &lt;ul&gt;
          &lt;li&gt;비즈니스적으로 의미가 있는 키&lt;/li&gt;
          &lt;li&gt;Ex) 전화번호, 주민등록번호 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;대리키/대체키 (Generate Value)
        &lt;ul&gt;
          &lt;li&gt;비즈니스적으로 상관없는 키&lt;/li&gt;
          &lt;li&gt;Ex) Generate Value, 랜덤 값, 유휴 값 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;예를 들어, 주민등록번호도 기본 키로 적절하지 않다.
    &lt;ul&gt;
      &lt;li&gt;Why? 갑자기 개인정보 보호의 목적으로 DB에 주민등록번호를 저장하지 말라 조건이 들어온다. 이때, 주민등록번호를 pk로 사용하고 있는 테이블뿐만 아니라 해당 테이블의 pk를 fk로 JOIN하고 있는 다른 테이블에서도 문제가 생긴다.&lt;/li&gt;
      &lt;li&gt;즉, 주민등록번호를 fk로 참조하고 있는 모든! 테이블을 마이그레이션 해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;권장하는-식별자-구성-전략&quot;&gt;권장하는 식별자 구성 전략&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;(Long형) + (대체키) + (적절한 키 생성 전략) 사용&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Long Type (아래 참고)&lt;/li&gt;
  &lt;li&gt;대체키 사용: 랜덤 값, 유휴 ID 등 비즈니스와 관계없는 값 사용&lt;/li&gt;
  &lt;li&gt;AUTO_INCREMENT 또는 Sequnce Object 사용&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[참고] Q.&lt;/strong&gt; id 값(pk 값)은 어떤 타입을 써야 할까?
    &lt;ul&gt;
      &lt;li&gt;int
        &lt;ul&gt;
          &lt;li&gt;0이 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Integer
        &lt;ul&gt;
          &lt;li&gt;10억 정도 까지만 가능하다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Long
        &lt;ul&gt;
          &lt;li&gt;채택!&lt;/li&gt;
          &lt;li&gt;Long의 크기가 Integer의 2배지만 애플리케이션 전체로 봤을 때의 영향은 작다고 볼 수 있다.&lt;/li&gt;
          &lt;li&gt;오히려 10억이 넘어갔을 때 해당 id 값을 타입을 변경하는 것이 더 어렵다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Mon, 12 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/12/primary-key-mapping.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/12/primary-key-mapping.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>genaratedvalue</category>
        
        <category>id</category>
        
        <category>pk</category>
        
        <category>strategy</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 엔티티 매핑 방법 (Entity Mapping)</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;!-- ![그림 추가]() --&gt;

&lt;p&gt;&lt;strong&gt;[들어가기 전]&lt;/strong&gt; JPA에서 중요한 것!&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;영속성 컨텍스트, JPA 내부 동작 등의 &lt;strong&gt;매커니즘 측면&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;JPA가 내부적으로 어떤 매커니즘으로 동작하는지.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;설계 측면&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;객체와 RDB를 어떻게 매핑해서 사용하는지.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;엔티티-매핑&quot;&gt;엔티티 매핑&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;기본적인 엔티티 매핑 소개
    &lt;ul&gt;
      &lt;li&gt;객체와 테이블 매핑
        &lt;ul&gt;
          &lt;li&gt;@Entity&lt;/li&gt;
          &lt;li&gt;@Table&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;필드와 컬럼 매핑
        &lt;ul&gt;
          &lt;li&gt;@Column&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;기본 키 매핑
        &lt;ul&gt;
          &lt;li&gt;@Id&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;연관관계 매핑
        &lt;ul&gt;
          &lt;li&gt;Ex) Member와 Team&lt;/li&gt;
          &lt;li&gt;@ManyToOne&lt;/li&gt;
          &lt;li&gt;@JoinColumn&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;객체와-테이블-매핑&quot;&gt;객체와 테이블 매핑&lt;/h2&gt;
&lt;h4 id=&quot;entity&quot;&gt;@Entity&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;@Entity가 붙은 클래스는 JPA가 관리하는 클래스로, 해당 클래스를 엔티티라고 한다.&lt;/li&gt;
  &lt;li&gt;JPA를 사용해서 테이블과 매핑할 클래스는 반드시 @Entity 를 붙여야 한다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[주의]&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;기본 생성자 필수&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;파라미터가 없는 public 또는 protected 생성자가 필요하다.&lt;/li&gt;
          &lt;li&gt;JPA spec으로 규정되어 있다.
            &lt;ul&gt;
              &lt;li&gt;Why? JPA를 구현해서 쓰는 라이브러리들이 다양한 기술(Ex. Reflection)을 사용해서 객체를 프록싱할 때 필요하기 때문.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;final 클래스, enum, interface, inner 클래스는 엔티티로 사용할 수 없다.&lt;/li&gt;
      &lt;li&gt;DB에 저장하고 싶은 필드에는 final을 사용할 수 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Entity 속성
&lt;!-- //// 추가  --&gt;
    &lt;ul&gt;
      &lt;li&gt;name
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Entity(name = &quot;Member&quot;)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;JPA에서 사용할 엔티티 이름을 지정한다.&lt;/li&gt;
          &lt;li&gt;기본값: 클래스 이름을 그대로 사용&lt;/li&gt;
          &lt;li&gt;같은 클래스 이름이 없으면 가급적 기본값을 사용하도록 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;table&quot;&gt;@Table&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;@Table은 엔티티와 매핑할 테이블을 지정하는 것이다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;@Table 속성
&lt;!-- //// 추가  --&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;name
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Table(name = &quot;MBR&quot;)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;매핑할 테이블 이름을 지정한다.&lt;/li&gt;
          &lt;li&gt;기본값: 엔티티 이름을 사용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;catalog
        &lt;ul&gt;
          &lt;li&gt;데이터베이스 catalog 매핑&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;schema
        &lt;ul&gt;
          &lt;li&gt;데이터베이스 schema 매핑&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;uniqueConstraints(DDL)
        &lt;ul&gt;
          &lt;li&gt;DDL 생성 시에 유니크 제약 조건 생성&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;데이터베이스-스키마-자동-생성&quot;&gt;데이터베이스 스키마 자동 생성&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;DDL을 애플리케이션 실행 시점(loading)에 자동으로 생성한다.&lt;/li&gt;
  &lt;li&gt;테이블 중심 -&amp;gt; 객체 중심&lt;/li&gt;
  &lt;li&gt;데이터베이스 방언을 활용해서 &lt;strong&gt;데이터베이스에 맞는 적절한 DDL&lt;/strong&gt;을 생성한다.
    &lt;ul&gt;
      &lt;li&gt;Ex) oracle: varchar2, MySQL: varchar 등
&lt;!-- - ////////////////////추가  --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이렇게 생성된 DDL은 개발 로컬 장비에서만 사용한다.
    &lt;ul&gt;
      &lt;li&gt;즉, 운영 서버에서는 사용하지 않거나, 적절히 다듬은 후 사용한다.&lt;/li&gt;
      &lt;li&gt;로컬 PC에서 개발할 때 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hibernate.hbm2ddl.auto&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;create&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hibernate.hbm2ddl.auto&lt;/code&gt; 옵션의 속성값&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;옵션&lt;/th&gt;
      &lt;th&gt;설명&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;create&lt;/td&gt;
      &lt;td&gt;기존 테이블 삭제 후 다시 생성 (DROP + CREATE)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;create-drop&lt;/td&gt;
      &lt;td&gt;create와 같으나 종료 시점에 테이블 DROP (테스트에서 사용하면 도움됨)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;update&lt;/td&gt;
      &lt;td&gt;변경 분만 반영 (운영 DB에서는 사용하면 안됨) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alter table ~&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;validate&lt;/td&gt;
      &lt;td&gt;엔티티와 테이블이 정상 매핑되었는지만 확인&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;none&lt;/td&gt;
      &lt;td&gt;아무 속성도 사용하지 않음&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[주의]&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;운영 장비에는 절대 create, create-drop, update를 사용하면 안된다.&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;개발 초기 단계(로컬 개발 서버)
        &lt;ul&gt;
          &lt;li&gt;create 또는 update&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;테스트 서버(여러 명이 같이 사용하는 개발 서버)
        &lt;ul&gt;
          &lt;li&gt;update 또는 validate&lt;/li&gt;
          &lt;li&gt;웬만하면 테스트 서버에서도 validate나 none을 쓰는 것이 좋다.&lt;/li&gt;
          &lt;li&gt;Why? 데이터가 많은 상태에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alter&lt;/code&gt;를 했을 때 자칫 시스템이 중단될 수도 있기 때문이다.&lt;/li&gt;
          &lt;li&gt;직접 스크립트를 짜서 적용해보고 문제가 없으면 DBA에게 검수를 받은 후 운영 서버에 적용하는 것을 권장한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;스테이징과 운영 서버
        &lt;ul&gt;
          &lt;li&gt;validate 또는 none&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[참고]&lt;/strong&gt; 데이터베이스 방언이란?
&lt;!-- -  ////////////////// --&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ddl-생성-기능&quot;&gt;DDL 생성 기능&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;제약 조건 추가 가능
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Column(nullable = false, length = 10)&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;회원 이름은 필수&lt;/li&gt;
          &lt;li&gt;10글자 초과 X&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Column(unique = true)&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;DB에 영향을 주는 것&lt;/li&gt;
          &lt;li&gt;해당 필드는 unique 함을 의미&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Table(uniqueConstraints = {@UniqueConstraint(name = &quot;NAME_AGE_UNIQUE&quot;, columnNames = {&quot;NAME&quot;, &quot;AGE&quot;})})&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;Unique 제약 조건 추가&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
    &lt;ul&gt;
      &lt;li&gt;즉, DB에만 영향을 주는 것이지 애플리케이션에 영향을 주는 것이 아니다.&lt;/li&gt;
      &lt;li&gt;JPA의 실행 매커니즘에 영향을 주는 것이 아니라 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alter table&lt;/code&gt;과 같은 스크립트가 실행되는 것을 말한다.&lt;/li&gt;
      &lt;li&gt;Cf) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insert&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update&lt;/code&gt;는 Runtime에 영향을 준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;필드와-컬럼-매핑&quot;&gt;필드와 컬럼 매핑&lt;/h2&gt;
&lt;h3 id=&quot;요구-사항-추가&quot;&gt;요구 사항 추가&lt;/h3&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;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;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RoleType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ADMIN&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;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;@Entity&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MBR&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Column&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Enumerated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EnumType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RoleType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;roleType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Temporal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TemporalType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TIMESTAMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;createDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Temporal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TemporalType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TIMESTAMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastModifiedDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Lob&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Transient&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Member&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;o&quot;&gt;}&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;div class=&quot;language-sql 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;k&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bigint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;createdDate&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;clob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;lastModifiedDate&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;roleType&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&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;nb&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;primary&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&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;h4 id=&quot;id&quot;&gt;@Id&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;pk 매핑&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;column&quot;&gt;@Column&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;컬럼 매핑&lt;/li&gt;
  &lt;li&gt;@Column 속성 
&lt;!-- - **[표 추가]** /////////// --&gt;
    &lt;ul&gt;
      &lt;li&gt;name
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Colunm(name = &quot;name&quot;)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;객체명과 DB 컬럼명을 다르게 하고 싶은 경우, DB 컬럼명으로 설정할 이름을 name 속성으로 적는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;insertable&lt;/li&gt;
      &lt;li&gt;updatable
        &lt;ul&gt;
          &lt;li&gt;컬럼을 수정했을 때 DB에 추가를 할 것인지 여부&lt;/li&gt;
          &lt;li&gt;update 문이 나갈 때 해당 컬럼을 반영할 것인지 여부&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Column(updatable = false)&lt;/code&gt;: 변경이 되어도 DB에 반영되지 않는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;nullable
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Column(nullable = false)&lt;/code&gt;: NOT NULL 제약조건이 된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;unique
        &lt;ul&gt;
          &lt;li&gt;잘 사용하지 않는다.
            &lt;ul&gt;
              &lt;li&gt;Why? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;constraint UK_ewkrjwel239flskdfj01 unique (name)&lt;/code&gt; 과 같이 이름을 랜덤으로 만든다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;이름에 대한 설정을 직접하려면 아래의 방법을 사용해야 한다.
            &lt;ul&gt;
              &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Table(uniqueConstraints = {@UniqueConstraint(name = &quot;NAME_AGE_UNIQUE&quot;, columnNames = {&quot;NAME&quot;, &quot;AGE&quot;})})&lt;/code&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;columnDefinition
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Column(columnDefinition = &quot;varchar(100) default 'EMPTY'&quot;)&lt;/code&gt;: 직접 컬럼 정보를 작성할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;length
        &lt;ul&gt;
          &lt;li&gt;문자 길이 제약 조건&lt;/li&gt;
          &lt;li&gt;String 타입에만 사용한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;precision
        &lt;ul&gt;
          &lt;li&gt;숫자가 엄청 큰 BigDecimal 의 경우 (Ex.&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private BigDecimal age;&lt;/code&gt;)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;enumerated&quot;&gt;@Enumerated&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Enum Type 매핑
    &lt;ul&gt;
      &lt;li&gt;Enum 객체 사용 시 해당 annotation을 사용&lt;/li&gt;
      &lt;li&gt;DB에는 Enum Type이 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;EnumType.ORDINAL
    &lt;ul&gt;
      &lt;li&gt;enum 순서를 데이터베이스에 저장 (기본값)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;EnumType.String
    &lt;ul&gt;
      &lt;li&gt;enum 이름을 데이터베이스에 저장&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[주의]&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;EnumType.ORDINAL 은 사용하지 않는다.&lt;/li&gt;
      &lt;li&gt;Why? 요구 사항에 따라 새로운 Type이 추가될 수 있기 때문에 순서가 변경될 수 있다.
        &lt;ul&gt;
          &lt;li&gt;즉, GUEST를 enum class 맨 앞에 추가 했을 때 GUEST와 USER 모두가 ‘0’으로 저장된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;즉, 필수처럼 EnumType.String 을 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;@Target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ElementType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;METHOD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ElementType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FIELD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Retention&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RetentionPolicy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RUNTIME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Enumerated&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;EnumType&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnumType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ORDINAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;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;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EnumType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ORDINAL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;STRING&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;EnumType&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;o&quot;&gt;}&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;h4 id=&quot;temporal&quot;&gt;@Temporal&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;날짜 Type (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.util.Date&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.util.Calendar&lt;/code&gt;) 매핑
    &lt;ul&gt;
      &lt;li&gt;날짜 타입 사용 시 해당 annotation을 사용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;java의 Date에는 날짜와 시간이 모두 존재한다. 그러나 DB의 Date에는 아래의 세 가지로 구분해서 사용한다&lt;/li&gt;
  &lt;li&gt;TemporalType enum class에는 세 가지가 존재한다.
    &lt;ul&gt;
      &lt;li&gt;DATE: 날짜, DB의 date 타입과 매핑
        &lt;ul&gt;
          &lt;li&gt;Ex. 2019-08-13&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;TIME: 시간, DB의 time 타입과 매핑
        &lt;ul&gt;
          &lt;li&gt;Ex. 14:20:38&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;TIMESTAMP: 날짜와 시간, DB의 timestamp 타입과 매핑
        &lt;ul&gt;
          &lt;li&gt;Ex. 2019-08-13 14:20:38&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;지금은 필요 없음&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;java 8의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalDate&lt;/code&gt;(date), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalDateTime&lt;/code&gt;(timestamp) 을 사용할 때는 생략이 가능하다.&lt;/li&gt;
      &lt;li&gt;hibernate에서 지원&lt;/li&gt;
      &lt;li&gt;Ex. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private LocalDate createDate&lt;/code&gt; 또는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private LocalDateTime createDateTime&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;lob&quot;&gt;@Lob&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;DB에서 varchar를 넘어서는 큰 내용을 넣고 싶은 경우에 해당 annotation을 사용&lt;/li&gt;
  &lt;li&gt;@Lob에는 지정할 수 있는 속성이 없다.&lt;/li&gt;
  &lt;li&gt;매핑하는 필드의 타입에 따라 DB의 BLOB, CLOB과 매핑된다.
    &lt;ul&gt;
      &lt;li&gt;필드의 타입이 문자열: CLOB
        &lt;ul&gt;
          &lt;li&gt;String, char[], java.sql.CLOB&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;그 외 나머지: BLOB
        &lt;ul&gt;
          &lt;li&gt;byte[], java.sql.BLOB&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;transient&quot;&gt;@Transient&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;특정 필드를 컬럼에 매핑하지 않음.
&lt;!-- 내용 확인 --&gt;&lt;/li&gt;
  &lt;li&gt;DB에 관계없이 메모리에서만 사용하고자 하는 객체에 해당 annotation을 사용
    &lt;ul&gt;
      &lt;li&gt;즉, 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;해당 annotation이 붙은 필드는 DB에 저장, 조회가 되지 않는다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sun, 11 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/11/entity-mapping.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/11/entity-mapping.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>mapping</category>
        
        <category>annotation</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 엔티티의 생명주기 (Entity LifeCycle)</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;엔티티의-생명주기-entity-lifecycle&quot;&gt;엔티티의 생명주기 (Entity LifeCycle)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;비영속(new/transient)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트와 전혀 관계가 없는 상태&lt;/li&gt;
      &lt;li&gt;객체를 생성’만’ 한 상태&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&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;c1&quot;&gt;// 객체를 생성한 상태 (비영속)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;회원1&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;영속(managed)&lt;/strong&gt; (아래 추가 설명)
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트에 저장된 상태&lt;/li&gt;
      &lt;li&gt;Entity가 영속성 컨텍스트에 의해 관리되는 상태&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityManager.persist(entity);&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;영속 상태가 된다고 바로 DB에 쿼리가 날라가지 않는다. (즉, DB 저장 X)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transaction.commit();&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;트랜잭션의 commit 시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날라간다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&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;c1&quot;&gt;// 객체를 생성한 상태 (비영속)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;회원1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;EntityManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManagerFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createEntityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&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;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;준영속(detached)&lt;/strong&gt; (아래 추가 설명)
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트에 저장되었다가 분리된 상태&lt;/li&gt;
      &lt;li&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;c1&quot;&gt;// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;detach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;삭제(removed)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;실제 DB 삭제를 요청한 상태
        &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;c1&quot;&gt;// 객체를 삭제한 상태&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;영속-상태와-준영속-상태&quot;&gt;영속 상태와 준영속 상태&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;영속 상태&lt;/strong&gt;란
    &lt;ul&gt;
      &lt;li&gt;1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.persist();&lt;/code&gt; 로 영속성 컨텍스트에 저장된 상태&lt;/li&gt;
      &lt;li&gt;2) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.find();&lt;/code&gt; 로 조회할 때 영속성 컨텍스트 1차 캐시에 없어서 DB에서 조회한 후 해당 Entity를 1차 캐시에 올라간 상태 (엔티티 매니저가 관리하는 상태)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;준영속 상태&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 상태&lt;/li&gt;
      &lt;li&gt;준영속 상태에서는 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
        &lt;ul&gt;
          &lt;li&gt;Dirty Checking, Update Query&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150L&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;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AAAAA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&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;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.find()&lt;/code&gt;: 1차 캐시에 없으므로 DB에서 조회한 Entity를 1차 캐시에 넣는다. (영속 상태)&lt;/li&gt;
  &lt;li&gt;변경 감지(Dirty Checking)
    &lt;ul&gt;
      &lt;li&gt;이름 변경에 대한 Entity 데이터 변화를 감지한다.&lt;/li&gt;
      &lt;li&gt;1차 캐시의 Entity와 Snapshot이 다른 것을 감지하고 UPDATE Query를 날린다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;준영속-상태로-만드는-방법-영속---준영속&quot;&gt;준영속 상태로 만드는 방법 (영속 -&amp;gt; 준영속)&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;entityManager.detach(entity): 특정 엔티티만 준영속 상태로 전환&lt;/li&gt;
  &lt;li&gt;entityManager.clear(): 영속성 컨텍스트를 완전히 초기화&lt;/li&gt;
  &lt;li&gt;entityManager.close(): 영속성 컨텍스트를 종료&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;detach&quot;&gt;detach&lt;/h4&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;c1&quot;&gt;// 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AAAAA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;detach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 영속성 컨텍스트에서 떼넨다. (더 이상 JPA 의 관리 대상이 아님.)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// DB에 insert query 가 날라가는 시점 (아무 일도 발생하지 않음.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.detach();&lt;/code&gt;: 해당 Entity를 영속성 컨텍스트에서 분리한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;JPA가 관리하지 않는 객체&lt;/strong&gt;가 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Transaction commit에서 아무 일도 발생하지 않는다.&lt;/li&gt;
  &lt;li&gt;즉, Entity가 변경이 되었는데 실제로 UPDATE Query가 나가지 않는다.&lt;/li&gt;
  &lt;li&gt;직접 쓸 일이 거의 없다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;clear&quot;&gt;clear&lt;/h4&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;c1&quot;&gt;// 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AAAAA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 간은 Entity 를 다시 조회&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// DB에 insert query 가 날라가는 시점 (아무일도 발생하지 않음.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.clear();&lt;/code&gt;: EntityManager 안에 있는 영속성 컨텍스트를 모두 지운다.
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트를 완전히 초기화&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;clear 후 같은 Entity를 다시 조회할 때는 SELECT Query가 다시 나간다.
    &lt;ul&gt;
      &lt;li&gt;총 2번의 SELECT 쿼리가 발생한다.&lt;/li&gt;
      &lt;li&gt;clear는 1차 캐시에 상관없이 쿼리를 확인하고 싶을 때 즉, testcase 작성 시에 도움이 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;close&quot;&gt;close&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;영속성 컨텍스트를 종료시킨다.&lt;/li&gt;
  &lt;li&gt;JPA 의 관리 대상이 아니게 된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Thu, 08 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/08/jpa-entity-lifecycle.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/08/jpa-entity-lifecycle.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>persistence-context</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 플러시(Flush)란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;플러시-flush&quot;&gt;플러시 (Flush)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;영속성 컨텍스트의 변경 내용을 DB 에 반영하는 것을 말한다.&lt;/li&gt;
  &lt;li&gt;Transaction commit 이 일어날 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush&lt;/code&gt;가 동작하는데, 이때 쓰기 지연 저장소에 쌓아 놨던 INSERT, UPDATE, DELETE SQL들이 DB에 날라간다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;주의!&lt;/strong&gt; 영속성 컨텍스트를 비우는 것이 아니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;쉽게 얘기해서 영속성 컨텍스트의 변경 사항들과 DB의 상태를 맞추는 작업이다.
    &lt;ul&gt;
      &lt;li&gt;플러시는 영속성 컨텍스트의 변경 내용을 DB에 동기화한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;플러시의-동작-과정&quot;&gt;플러시의 동작 과정&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;변경을 감지한다. (Dirty Checking)&lt;/li&gt;
  &lt;li&gt;수정된 Entity를 쓰기 지연 SQL 저장소에 등록한다.&lt;/li&gt;
  &lt;li&gt;쓰기 지연 SQL 저장소의 Query를 &lt;strong&gt;DB에 전송&lt;/strong&gt;한다. (등록, 수정, 삭제 Query)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;flish가 발생한다고 해서 commit이 이루어지는 것이 아니고 flush 다음에 실제 commit이 일어난다.&lt;/li&gt;
  &lt;li&gt;플러시가 동작할 수 있는 이유는 데이터베이스 트랜잭션(작업 단위)이라는 개념이 있기 때문이다.
    &lt;ul&gt;
      &lt;li&gt;트랜잭션이 시작되고 해당 트랜잭션이 commit 되는 시점 직전에만 동기화 (변경 내용을 날림) 해주면 되기 때문에, 그 사이에서 플러시 매커니즘의 동작이 가능한 것이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[참고]&lt;/strong&gt; JPA는 기본적으로 데이터를 맞추거나 동시성에 관련된 것들은 데이터베이스 트랜잭션에 위임한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;영속성-컨텍스트를-플러시하는-방법&quot;&gt;영속성 컨텍스트를 플러시하는 방법&lt;/h3&gt;
&lt;h4 id=&quot;1-emflush-을-통한-직접-호출&quot;&gt;1. em.flush() 을 통한 직접 호출&lt;/h4&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;c1&quot;&gt;// 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 강제 호출 (쿼리가 DB 에 반영됨)&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DB INSERT Query 가 즉시 나감. -- flush() 호출 후 --  Transaction commit 됨.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// DB에 insert query 가 날라가는 시점 (Transaction commit)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; 플러시가 일어나면 1차 캐시가 모두 지워질까?
    &lt;ul&gt;
      &lt;li&gt;NO! 그대로 남아있다.&lt;/li&gt;
      &lt;li&gt;쓰기 지연 SQL 저장소에 있는 Query들만 DB에 전송까지만 되는 과정일뿐이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-트랜잭션-커밋-시-플러시-자동-호출&quot;&gt;2. 트랜잭션 커밋 시 플러시 자동 호출&lt;/h4&gt;

&lt;h4 id=&quot;3-jpql-쿼리-실행-시-플러시-자동-호출&quot;&gt;3. JPQL 쿼리 실행 시 플러시 자동 호출&lt;/h4&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;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 중간에 JPQL 실행&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;select m from Member m&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;members&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getResultList&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;ul&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; memberA, B, C 를 영속성 컨텍스트에 저장한 상태에서 바로 조회하면 조회가 될까?
    &lt;ul&gt;
      &lt;li&gt;조회가 되지 않는다.&lt;/li&gt;
      &lt;li&gt;DB 에 Query로도 날라가야 반영이 될텐데 INSERT Query 자체가 날라가지 않은 상태이다. 이런 상태에서 JPQL로 DB에서 가져오는 SELECT Query 요청을 한 것이므로 당연히 조회되지 않는다.&lt;/li&gt;
      &lt;li&gt;JPQL은 SQL로 번역이 돼서 실행되는 것이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이 때문에 JPA의 기본 모드는 JPQL 쿼리 실행 시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;를 자동으로 날린다.
    &lt;ul&gt;
      &lt;li&gt;즉, JPQL 쿼리 실행 시 플러시 자동 호출로 인해 위의 코드는 조회가 가능하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;플러시-모드-옵션&quot;&gt;플러시 모드 옵션&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;em.setFlushMode(FlushModeType.COMMIT);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;FlushModeType.AUTO&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;기본 설정 값&lt;/li&gt;
  &lt;li&gt;Transaction 을 commit 하거나 Query를 실행할 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;를 먼저 수행한다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;FlushModeType.COMMIT&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Transaction commit 할때만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;를 먼저 수행한다.&lt;/li&gt;
  &lt;li&gt;Query를 실행할 때는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;를 먼저 수행하지 않는다.&lt;/li&gt;
  &lt;li&gt;이점: persist 한 것과 전혀 다른 테이블을 조회하는 경우&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Wed, 07 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/07/what-is-flush.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/07/what-is-flush.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>persistence-context</category>
        
        <category>flush</category>
        
        
      </item>
    
      <item>
        <title>[JPA] 영속성 컨텍스트(Persistence Context)란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;영속성-관리&quot;&gt;영속성 관리&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;JPA 에서 가장 중요한 2가지
    &lt;ul&gt;
      &lt;li&gt;객체와 관계형 DB 매핑하기 (Object Relational Mapping) - &lt;em&gt;설계 관련&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;영속성 컨텍스트 - &lt;em&gt;JPA 내부 동작&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;entitymanagerfactory와-entitymanager&quot;&gt;EntityManagerFactory와 EntityManager&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;EntityManagerFactory&lt;/em&gt;는 고객의 요청이 올 때마다 (thread가 하나 생성될 때마다) EntityManager를 생성한다.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;EntityManager&lt;/em&gt;는 내부적으로 DB connection pool을 사용해서 DB에 접근한다.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;사진 추가&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EntityManagerFactory&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;JPA 는 EntityManagerFactory 를 만들어야 한다.&lt;/li&gt;
      &lt;li&gt;application loading 시점에 DB 당 딱 하나만 생성되어야 한다.
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(&quot;hello&quot;);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManagerFactory.close();&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;WAS 가 종료되는 시점에 EntityManagerFactory 를 닫는다.&lt;/li&gt;
          &lt;li&gt;그래야 내부적으로 Connection pooling 에 대한 Resource 가 Release 된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EntityManager&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;실제 Transaction 단위를 수행할 때마다 생성한다.&lt;/li&gt;
      &lt;li&gt;즉, 고객의 요청이 올 때마다 사용했다가 닫는다.&lt;/li&gt;
      &lt;li&gt;thread 간에 공유하면 안된다. (사용하고 버려야 한다.)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.close();&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;Transaction 수행 후에는 반드시 EntityManager 를 닫는다.&lt;/li&gt;
          &lt;li&gt;그래야 내부적으로 DB Connection 을 반환한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;EntityTransaction&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Data 를 “변경”하는 모든 작업은 반드시 Transaction 안에서 이루어져야 한다.
        &lt;ul&gt;
          &lt;li&gt;단순한 조회의 경우는 상관없음.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityTransaction tx = entityManager.getTransaction();&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;tx.begin(); : Transaction 시작&lt;/li&gt;
      &lt;li&gt;tx.commit(); : Transaction 수행&lt;/li&gt;
      &lt;li&gt;tx.rollback(); : 작업에 문제가 생겼을 시&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;영속성-컨텍스트persistence-context란&quot;&gt;영속성 컨텍스트(Persistence Context)란&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;JPA를 이해하는데 가장 중요한 용어이다.
    &lt;ul&gt;
      &lt;li&gt;논리적인 개념으로, 눈에 보이지 않는다.&lt;/li&gt;
      &lt;li&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;“&lt;strong&gt;Entity를 영구 저장하는 환경&lt;/strong&gt;”&lt;/span&gt;이라는 뜻&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityManager.persist(entity);&lt;/code&gt; 의 동작 설명
    &lt;ul&gt;
      &lt;li&gt;실제로는 DB에 저장하는 것이 아니라 영속성 컨텍스트를 통해서 &lt;strong&gt;Entity를 영속화한다&lt;/strong&gt;는 뜻이다.&lt;/li&gt;
      &lt;li&gt;정확히 말하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;persist()&lt;/code&gt; 시점에는 &lt;strong&gt;Entity를 영속성 컨텍스트에 저장하는 것&lt;/strong&gt;이다.
&lt;!-- - DB 저장은 이후이다. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;EntityManager를 통해서 영속성 컨텍스트에 접근한다.
&lt;img src=&quot;&quot; alt=&quot;사진 추가&quot; /&gt;
    &lt;ul&gt;
      &lt;li&gt;EntityManager가 생성되면 1:1로 영속성 컨텍스트가 생성된다. 
&lt;!-- - 스프링에서 EntityManager를 주입 받아서 쓰면, 같은 트랜잭션의 범위에 있는 EntityManager는 동일 영속성 컨텍스트에 접근한다. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;엔티티의-생명주기-entity-lifecycle&quot;&gt;&lt;a href=&quot;url 추가&quot;&gt;엔티티의 생명주기 (Entity LifeCycle)&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;비영속(new/transient)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트와 전혀 관계가 없는 상태&lt;/li&gt;
      &lt;li&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;c1&quot;&gt;// 객체를 생성한 상태 (비영속)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;회원1&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;영속(managed)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트에 저장된 상태&lt;/li&gt;
      &lt;li&gt;Entity가 영속성 컨텍스트에 의해 관리되는 상태
        &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;c1&quot;&gt;// 객체를 생성한 상태 (비영속)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;회원1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;EntityManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManagerFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createEntityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&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;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EntityManager.persist(entity);&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;영속 상태가 된다고 바로 DB에 쿼리가 날라가지 않는다. (즉, DB 저장 X)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transaction.commit();&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;트랜잭션의 commit 시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날라간다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;준영속(detached)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영속성 컨텍스트에 저장되었다가 분리된 상태&lt;/li&gt;
      &lt;li&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;c1&quot;&gt;// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;detach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;삭제(removed)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;실제 DB 삭제를 요청한 상태
        &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;c1&quot;&gt;// 객체를 삭제한 상태&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;영속성-컨텍스트의-이점&quot;&gt;영속성 컨텍스트의 이점&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Applicaion 과 DB 사이의 중간 계층의 영속성 컨텍스트가 존재하는 이유
    &lt;ul&gt;
      &lt;li&gt;버퍼링, 캐싱 등의 이점&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;1-1차-캐시&quot;&gt;1. 1차 캐시&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;영속성 컨텍스트 내부에는 1차 캐시가 존재한다.
    &lt;ul&gt;
      &lt;li&gt;1차 캐시를 영속성 컨텍스트라고 이해해도 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Map&amp;lt;Key, Value&amp;gt; 로 1차 캐시에 저장된다.
    &lt;ul&gt;
      &lt;li&gt;key : @Id로 선언한 필드 값 (DB pk)&lt;/li&gt;
      &lt;li&gt;value : 해당 Entity 자체&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;회원1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태) */&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// DB 저장 X, 1차 캐시에 저장됨&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;// 1차 캐시에서 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findMember&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Member1&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;ul&gt;
  &lt;li&gt;1차 캐시에 Entity 가 있을 때의 이점
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;조회&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.find()&lt;/code&gt; 를 하면 DB보다 먼저, 1차 캐시를 조회한다.&lt;/li&gt;
      &lt;li&gt;1차 캐시에 해당 Entity가 존재하면 바로 반환한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; 1차 캐시에 조회하고자하는 Entity가 없다면?
    &lt;ul&gt;
      &lt;li&gt;1) DB에서 조회 한다.&lt;/li&gt;
      &lt;li&gt;2) 해당 Entity를 DB에서 꺼내와 1차 캐시에 저장한다.&lt;/li&gt;
      &lt;li&gt;3) Entity를 반환한다.&lt;/li&gt;
      &lt;li&gt;이후에 다시 해당 Entity를 조회하면 1차 캐시에 있는 Entity를 반환한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;그러나, 사실 1차 캐시는 큰 성능 이점을 가지고 있지 않다.
    &lt;ul&gt;
      &lt;li&gt;EntityManager는 Transaction 단위로 만들고 해당 DB Transaction이 끝날 때 (사용자의 요청에 대한 비지니스가 끝날 때) 같이 종료된다.&lt;/li&gt;
      &lt;li&gt;즉, 1차 캐시도 모두 날라가기 때문에 굉장히 짧은 찰나의 순간에만 이득이 있다. (DB의 한 Transaction 안에서만 효과가 있다.)&lt;/li&gt;
      &lt;li&gt;하지만, 비지니스 로직이 굉장히 복잡한 경우에는 효과가 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[참고]&lt;/strong&gt; 2차 캐시
    &lt;ul&gt;
      &lt;li&gt;여러 명이 사용하는 캐시&lt;/li&gt;
      &lt;li&gt;Applicaion 전체에서 공유하는 캐시 
  &lt;!-- * SELECT 쿼리가 안나간다. 한 트랜잭션 내에서. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-동일성-보장-identity&quot;&gt;2. 동일성 보장 (Identity)&lt;/h3&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;member1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 동일성 비교 true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;영속 Entity의 동일성(== 비교)을 보장한다.
    &lt;ul&gt;
      &lt;li&gt;즉, “==” 비교가 true 임을 보장한다.&lt;/li&gt;
      &lt;li&gt;member1에 해당하는 Entity를 2번 조회하면 1차 캐시에 의해 같은 Reference 로 인식된다.&lt;/li&gt;
      &lt;li&gt;하나의 Transaction 안에서 같은 Entity 비교 시 true&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 &lt;strong&gt;DB가 아닌 아닌 애플리케이션 차원에서 제공&lt;/strong&gt;한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-엔티티-등록-시-트랜잭션을-지원하는-쓰기-지연-transactional-write-behind&quot;&gt;3. 엔티티 “등록” 시 트랜잭션을 지원하는 쓰기 지연 (Transactional Write-Behind)&lt;/h3&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;EntityManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createEntityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;EntityTransaction&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// EntityManager는 데이터 변경 시 트랜잭션을 시작해야 한다.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Transaction 시작&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;entityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 이때까지 INSERT SQL을 DB에 보내지 않는다.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 커밋하는 순간 DB에 INSERT SQL을 보낸다.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Transaction 커밋 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.persist()&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;JPA가 insert SQL을 계속 쌓고 있는 상태&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transaction.commit()&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;커밋하는 시점에 insert SQL을 동시에 DB에 보낸다.&lt;/li&gt;
      &lt;li&gt;동시에 쿼리들을 쫙 보낸다.(쿼리를 보내는 방식은 동시 or 하나씩 옵션에 따라)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entityManager.persist(memberA)&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;1) memberA가 &lt;strong&gt;1차 캐시&lt;/strong&gt;에 저장한다.&lt;/li&gt;
      &lt;li&gt;2) 1)과 동시에 JPA가 Entity를 분석하여 insert Query를 만든다.&lt;/li&gt;
      &lt;li&gt;3) insert Query를 &lt;strong&gt;쓰기 지연 SQL 저장소&lt;/strong&gt; 라는 곳에 쌓는다.&lt;/li&gt;
      &lt;li&gt;4) DB에 바로 넣지 않고 기다린다.&lt;/li&gt;
      &lt;li&gt;5) memberB도 동일.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transaction.commit()&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;6) &lt;strong&gt;쓰기 지연 SQL 저장소&lt;/strong&gt;에 쌓여있는 Query들을 DB로 날린다. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;)
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt; 는 1차캐시를 지우지는 않는다. 쿼리들을 DB에 날려서 DB와 싱크를 맞추는 역할을 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;7) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt; 후에 실제 DB Transaction이 커밋된다. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit()&lt;/code&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;버퍼링 기능&lt;/em&gt;&lt;/strong&gt; 이라고 할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;DB에 쿼리를 날리는 것에 대한 옵션 설정을 통한 최적화 가능
        &lt;ul&gt;
          &lt;li&gt;jpa의 이런 기능을 잘 활용하면 성능 개선을 쉽게 할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;jdbc 일괄 처리 옵션 (jdbc batch option)
        &lt;ul&gt;
          &lt;li&gt;persistence.xml에 아래와 같은 옵션을 줄 수 있다.&lt;/li&gt;
          &lt;li&gt;commit 직전까지 insert query를 해당 사이즈 만큼 모아서 한번에 처리한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;property name=&quot;hibernate.jdbc.batch_size&quot; value=10/&amp;gt;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;4-엔티티-수정-시-변경-감지-dirty-checking&quot;&gt;4. 엔티티 “수정” 시 변경 감지 (Dirty Checking)&lt;/h3&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;EntityManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createEntityManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;EntityTransaction&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Transaction 시작&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 영속 엔티티 조회&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;memberA&quot;&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;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hi&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// em.update(member) 또는 em.persist(member) 이런 코드가 있어야 하지 않을까?&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Transaction 커밋&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Entity 데이터 수정 시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update()&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;persist()&lt;/code&gt;로 영속성 컨텍스트에 해당 데이터를 업데이트 해달라고 알려줘야 하지 않을까?
    &lt;ul&gt;
      &lt;li&gt;NO!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Entity 데이터만 수정하고 commit 하면 알아서 DB에 반영된다.&lt;/li&gt;
  &lt;li&gt;즉, 데이터를 set하면 해당 데이터의 변경을 감지하여 자동으로 UPDATE Query가 나가는 것이다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;변경-감지-dirty-checking&quot;&gt;변경 감지 (Dirty Checking)&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;그림 추가&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;1차 캐시
    &lt;ul&gt;
      &lt;li&gt;@Id, Entity, Snapshot (값을 읽어온 최초의 상태)&lt;/li&gt;
      &lt;li&gt;Snapshot: 영속성 컨텍스트에 최초로 값이 들어왔을 때의 상태값을 저장한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;변경 감지 매커니즘
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transaction.commit()&lt;/code&gt; 을 하면&lt;/li&gt;
      &lt;li&gt;1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flush()&lt;/code&gt;가 일어날 때 &lt;strong&gt;엔티티와 스냅샷을 일일이 비교&lt;/strong&gt;한다.&lt;/li&gt;
      &lt;li&gt;2) 변경사항이 있으면 UPDATE Query를 만든다.&lt;/li&gt;
      &lt;li&gt;3) 해당 UPDATE Query를 쓰기 지연 SQL 저장소에 넣는다.&lt;/li&gt;
      &lt;li&gt;4) UPDATE Query를 DB에 반영한 후 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit()&lt;/code&gt;한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[참고]&lt;/strong&gt; @DynamicUpdate
    &lt;ul&gt;
      &lt;li&gt;Dirty Checking으로 생성되는 update 쿼리는 기본적으로 모든 필드를 업데이트한다.&lt;/li&gt;
      &lt;li&gt;@DynamicUpdate를 통해 엔티티 수정 시 변경된 필드만 반영되도록 할 수 있다.&lt;/li&gt;
      &lt;li&gt;https://jojoldu.tistory.com/415&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;5-엔티티-삭제&quot;&gt;5. 엔티티 삭제&lt;/h3&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;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;memberA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&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;위의 Entity 수정에서의 매커니즘과 동일&lt;/li&gt;
  &lt;li&gt;Transaction의 commit 시점에 DELETE Query가 나간다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 06 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/06/persistence-context.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/06/persistence-context.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        <category>persistence-context</category>
        
        
      </item>
    
      <item>
        <title>[JPA] JPA란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;ORM이란&lt;/li&gt;
    &lt;li&gt;JPA란&lt;/li&gt;
    &lt;li&gt;JPA의 동작 과정&lt;/li&gt;
    &lt;li&gt;JPA를 사용해야 되는 이유&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ormobject-relational-mapping-이란&quot;&gt;ORM(Object-relational mapping) 이란&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Object-relational mapping (객체 관계 매핑)
    &lt;ul&gt;
      &lt;li&gt;객체는 객체대로 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계한다.&lt;/li&gt;
      &lt;li&gt;ORM 프레임워크가 중간에서 매핑해준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;대중적인 언어에는 대부분 ORM 기술이 존재한다.&lt;/li&gt;
  &lt;li&gt;ORM은 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;객체와 RDB &lt;strong&gt;두 기둥 위에 있는 기술&lt;/strong&gt;&lt;/span&gt; 이다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;jpajava-persistence-api-란&quot;&gt;JPA(Java Persistence API) 란&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;EJB
    &lt;ul&gt;
      &lt;li&gt;과거의 자바 표준 (Entity Bean)&lt;/li&gt;
      &lt;li&gt;과거의 ORM&lt;/li&gt;
      &lt;li&gt;문제?
        &lt;ul&gt;
          &lt;li&gt;코드가 매우 지저분하다.&lt;/li&gt;
          &lt;li&gt;API의 복잡성이 높다. (interface를 많이 구현해야 함)&lt;/li&gt;
          &lt;li&gt;속도가 느리다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Hibernate
    &lt;ul&gt;
      &lt;li&gt;ORM 프레임워크, Open Source SW&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;‘Gavin King’&lt;/em&gt; 과 시러스 테크놀로지스 출신 동료들이 EJB2 스타일의 Entity Beans 이용을 대체할 목적으로 개발하였다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;JPA (Java Persistence API)
    &lt;ul&gt;
      &lt;li&gt;현재 자바 진영의 ORM 기술 표준으로, &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;인터페이스의 모음&lt;/strong&gt;&lt;/span&gt;이다.
        &lt;ul&gt;
          &lt;li&gt;즉, 실제로 동작하는 것이 아니다.&lt;/li&gt;
          &lt;li&gt;JPA 인터페이스를 구현한 대표적인 오픈소스가 Hibernate라고 할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;JPA 2.1 표준 명세를 구현한 3가지 &lt;strong&gt;구현체&lt;/strong&gt;: Hibernate, EclipseLink, DataNucleus
        &lt;ul&gt;
          &lt;li&gt;&lt;img src=&quot;/images/inflearn-jpa/implementation-of-jpa.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;버전
        &lt;ul&gt;
          &lt;li&gt;JPA 1.0(JSR 220) 2006년 : 초기 버전. 복합 키와 연관관계 기능이 부족&lt;/li&gt;
          &lt;li&gt;JPA 2.0(JSR 317) 2009년 : 대부분의 ORM 기능을 포함, JPA Criteria 추가&lt;/li&gt;
          &lt;li&gt;JPA 2.1(JSR 338) 2013년 : 스토어드 프로시저 접근, 컨버터(Converter), 엔티티 그래프 기능이 추가&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Cf) Spring Framework
    &lt;ul&gt;
      &lt;li&gt;Application 프레임워크, Open Source SW&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;‘Rod Johnson’&lt;/em&gt; 이 EJB의 여러 문제를 해결하고, 엔터프라이즈 애플리케이션 개발을 좀 더 쉽게 하기 위한 목적으로 만들었다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;jpa의-동작-과정&quot;&gt;JPA의 동작 과정&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/jpa-basic-structure.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;JPA는 애플리케이션과 JDBC 사이에서 동작한다.
    &lt;ul&gt;
      &lt;li&gt;개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하여 DB와 통신한다.&lt;/li&gt;
      &lt;li&gt;즉, 개발자가 직접 JDBC API를 쓰는 것이 아니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;저장-과정&quot;&gt;저장 과정&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/jpa-insert-structure.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ex) MemberDAO에서 객체를 저장하고 싶을 때
    &lt;ul&gt;
      &lt;li&gt;개발자는 JPA에 Member 객체를 넘긴다.&lt;/li&gt;
      &lt;li&gt;JPA는
        &lt;ul&gt;
          &lt;li&gt;1) Member 엔티티를 분석한다.&lt;/li&gt;
          &lt;li&gt;2) INSERT SQL을 생성한다.&lt;/li&gt;
          &lt;li&gt;3) JDBC API를 사용하여 SQL을 DB에 날린다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;조회-과정&quot;&gt;조회 과정&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/jpa-select-structure.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ex) Member 객체를 조회하고 싶을 때
    &lt;ul&gt;
      &lt;li&gt;개발자는 member의 pk 값을 JPA에 넘긴다.&lt;/li&gt;
      &lt;li&gt;JPA는
        &lt;ul&gt;
          &lt;li&gt;1) 엔티티의 매핑 정보를 바탕으로 적절한 SELECT SQL을 생성한다.&lt;/li&gt;
          &lt;li&gt;2) JDBC API를 사용하여 SQL을 DB에 날린다.&lt;/li&gt;
          &lt;li&gt;3) DB로부터 결과를 받아온다.&lt;/li&gt;
          &lt;li&gt;4) 결과(ResultSet)를 객체에 모두 매핑한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;쿼리를 JPA가 만들어 주기 때문에 Object와 RDB 간의 &lt;strong&gt;패러다임 불일치를 해결&lt;/strong&gt;할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;jpa를-왜-사용해야-하는가&quot;&gt;JPA를 왜 사용해야 하는가?&lt;/h2&gt;
&lt;h3 id=&quot;1-sql-중심적인-개발에서-객체-중심으로-개발&quot;&gt;1. SQL 중심적인 개발에서 객체 중심으로 개발&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2019/08/03/reason-why-use-jpa.html&quot;&gt;SQL 중심적인 개발의 문제점 참고&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-생산성&quot;&gt;2. 생산성&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;JPA를 사용하는 것은 마치 Java Collection에 데이터를 넣었다 빼는 것처럼 사용할 수 있게 만든 것이다.&lt;/li&gt;
  &lt;li&gt;간단한 CRUD
    &lt;ul&gt;
      &lt;li&gt;저장: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jpa.persist(member)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;조회: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Member member = jpa.find(memberId)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;수정: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.setName(&quot;변경할 이름&quot;)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;삭제: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jpa.remove(member)&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;특히, 수정이 굉장히 간단하다.
    &lt;ul&gt;
      &lt;li&gt;객체를 변경하면 그냥 알아서 DB에 UPDATE Query가 나간다.
  &lt;!-- - 트랜잭션이 끝나는 시점에 변경된 내용 찾아서 DB에 넣어준다. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-유지보수&quot;&gt;3. 유지보수&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;기존: 필드 변경 시 모든 SQL을 수정해야 한다.&lt;/li&gt;
  &lt;li&gt;JPA: 필드만 추가하면 된다. SQL은 JPA가 처리하기 때문에 손댈 것이 없다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;4-object와-rdb-간의-패러다임-불일치-해결&quot;&gt;4. Object와 RDB 간의 패러다임 불일치 해결&lt;/h3&gt;
&lt;h4 id=&quot;1-jpa와-상속&quot;&gt;1) JPA와 상속&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/rdb-super-sub-relation.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;저장
    &lt;ul&gt;
      &lt;li&gt;개발자가 할 일
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jpa.persist(album);&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;나머진 JPA가 처리
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO ITEM ...&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO ALBUM ...&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;조회
    &lt;ul&gt;
      &lt;li&gt;개발자가 할 일
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Album album = jpa.find(Album.class, albumId);&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;나머진 JPA가 처리
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELECT I.*, A.* FROM ITEM I JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-jpa와-연관관계&quot;&gt;2) JPA와 연관관계&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;객체의 참조로 연관관계 저장 가능
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.setTeam(team);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jpa.persist(member);&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-jpa와-객체-그래프-탐색&quot;&gt;3) JPA와 객체 그래프 탐색&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemberService&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&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;cm&quot;&gt;/* 직접 구현한 DAO에서 객체를 가져온 경우 */&lt;/span&gt;
          &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
          &lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&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;n&quot;&gt;member1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDelivery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; 
          &lt;span class=&quot;cm&quot;&gt;/* JPA를 통해서 객체를 가져온 경우 */&lt;/span&gt;
          &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jpa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
          &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&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;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDelivery&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;내가 아닌 다른 개발자가 직접 구현한 DAO에서 가져오는 경우
    &lt;ul&gt;
      &lt;li&gt;DAO에서 직접 어떤 쿼리를 날렸는지 확인하지 않는 이상, 그래프 형태의 관련된 객체들을 모두 잘 가져왔는지 알 수가 없다.&lt;/li&gt;
      &lt;li&gt;즉, 반환한 엔티티를 신뢰하고 사용할 수 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;JPA를 통해서 가져오는 경우
    &lt;ul&gt;
      &lt;li&gt;객체 그래프를 완전히 자유롭게 탐색할 수 있게 된다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;지연 로딩 전략(Lazy Loading)&lt;/strong&gt; 사용
        &lt;ul&gt;
          &lt;li&gt;관련된 객체를 &lt;strong&gt;사용하는 그 시점에&lt;/strong&gt; SELECT Query를 날려서 객체를 가져오는 전략&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;4-jpa와-비교하기&quot;&gt;4) JPA와 비교하기&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&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;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jpa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// DB에서 가져옴 &lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jpa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1차 캐시에서 가져옴&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&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;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;5-jpa의-성능-최적화-기능&quot;&gt;5. JPA의 성능 최적화 기능&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;중간 계층이 있는 경우 아래의 방법으로 성능을 개선할 수 있는 기능이 존재한다.
    &lt;ul&gt;
      &lt;li&gt;모아서 쓰는 &lt;em&gt;버퍼링 기능&lt;/em&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;JPA도 JDBC API와 DB 사이에 존재하기 때문에 위의 두 기능이 존재한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;1-1차-캐시와-동일성identity-보장---캐싱-기능&quot;&gt;1) 1차 캐시와 동일성(identity) 보장 - &lt;em&gt;캐싱 기능&lt;/em&gt;&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;같은 트랜잭션 안에서는 같은 엔티티를 반환 - &lt;strong&gt;약간의&lt;/strong&gt; 조회 성능 향상 (크게 도움 X)
    &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;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jpa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// SQL &lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jpa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 캐시 (SQL 1번만 실행, m1을 가져옴)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;결과적으로, SQL을 한 번만 실행한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;2-트랜잭션을-지원하는-쓰기-지연transactional-write-behind---버퍼링-기능&quot;&gt;2) 트랜잭션을 지원하는 쓰기 지연(transactional write-behind) - &lt;em&gt;버퍼링 기능&lt;/em&gt;&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;INSERT
    &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;cm&quot;&gt;/** 1. 트랜잭션을 커밋할 때까지 INSERT SQL을 모음 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&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;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;persist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;// -- 여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다. --&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/** 2. JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&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;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;[트랜잭션]을 commit 할 때까지 INSERT SQL을 메모리에 쌓는다.
    &lt;ul&gt;
      &lt;li&gt;이렇게 하지 않으면 DB에 INSERT Query를 날리기 위한 네트워크를 3번 타게 된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;JDBC Batch SQL 기능을 사용해서 한 번에 SQL을 전송한다.
    &lt;ul&gt;
      &lt;li&gt;JDBC Batch를 사용하면 코드가 굉장히 지저분해진다.&lt;/li&gt;
      &lt;li&gt;지연 로딩 전략(Lazy Loading) 옵션을 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;UPDATE
    &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;cm&quot;&gt;/** 1. UPDATE, DELETE로 인한 로우(ROW)락 시간 최소화 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;begin&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;n&quot;&gt;changeMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;  
&lt;span class=&quot;n&quot;&gt;deleteMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;  
&lt;span class=&quot;err&quot;&gt;비즈니스&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;로직&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;수행&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// 비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.    &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/** 2. 트랜잭션 커밋 시 UPDATE, DELETE SQL 실행하고, 바로 커밋 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&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;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;UPDATE, DELETE로 인한 로우(ROW)락 시간 최소화&lt;/li&gt;
  &lt;li&gt;트랜잭션 커밋 시 UPDATE, DELETE SQL 실행하고, 바로 커밋&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;3-지연-로딩lazy-loading&quot;&gt;3) 지연 로딩(Lazy Loading)&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;지연 로딩&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;객체가 실제로 사용될 때 로딩하는 전략 
&lt;img src=&quot;/images/inflearn-jpa/lazy-loading.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memberDAO.find(memberId)&lt;/code&gt;에서는 Member 객체에 대한 SELECT 쿼리만 날린다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Team team = member.getTeam()&lt;/code&gt;로 Team 객체를 가져온 후에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;team.getName()&lt;/code&gt;처럼 실제로 team 객체를 건드릴 때!
        &lt;ul&gt;
          &lt;li&gt;즉, &lt;strong&gt;값이 실제로 필요한 시점에&lt;/strong&gt; JPA가 Team에 대한 SELECT 쿼리를 날린다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Member와 Team 객체 각각 따로 조회하기 때문에 네트워크를 2번 타게 된다.
        &lt;ul&gt;
          &lt;li&gt;Member를 사용하는 경우에 대부분 Team도 같이 필요하다면 &lt;em&gt;즉시 로딩&lt;/em&gt;을 사용한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;즉시 로딩&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;JOIN SQL로 한 번에 연관된 객체까지 미리 조회하는 전략 
&lt;img src=&quot;/images/inflearn-jpa/instant-loading.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Join을 통해 항상 연관된 모든 객체를 같이 가져온다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;애플리케이션 개발할 때는 모두 지연 로딩으로 설정한 후에, 성능 최적화가 필요할 때에 옵션을 변경하는 것을 추천한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;6-데이터-접근-추상화와-벤더-독립성&quot;&gt;6. 데이터 접근 추상화와 벤더 독립성&lt;/h3&gt;

&lt;h3 id=&quot;7-표준&quot;&gt;7. 표준&lt;/h3&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sun, 04 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        
      </item>
    
      <item>
        <title>[JPA] JPA를 사용하는 이유</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;SQL에 의존적인 개발을 하게 된 배경&lt;/li&gt;
    &lt;li&gt;SQL 중심적인 개발의 문제점
      &lt;ul&gt;
        &lt;li&gt;지루한 코드의 무한 반복&lt;/li&gt;
        &lt;li&gt;객체 지향과 관계형 데이터베이스 간의 패러다임 불일치&lt;/li&gt;
        &lt;li&gt;객체(Object)와 관계형 데이터베이스(RDB)의 차이&lt;/li&gt;
        &lt;li&gt;모델링 과정에서의 문제&lt;/li&gt;
        &lt;li&gt;객체 그래프 탐색에서의 문제&lt;/li&gt;
        &lt;li&gt;“비교하기” 에서의 차이&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;배경&quot;&gt;배경&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;JPA와 모던 자바 데이터 저장 기술
    &lt;ul&gt;
      &lt;li&gt;애플리케이션 &lt;strong&gt;객체 지향&lt;/strong&gt; 언어 (Java, Scala 등) + &lt;strong&gt;관계형 DB&lt;/strong&gt; (Oracle, MySQL 등)&lt;/li&gt;
      &lt;li&gt;객체를 영구 보관하는 다양한 저장소 (RDB, NoSQL, File, OODB 등) 가 존재하지만 현실적인 대안은 관계형 DB다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;즉, 객체를 관계형 DB에 저장해서 관리하는 것이 중요하다.
    &lt;ul&gt;
      &lt;li&gt;관계형 DB를 사용하려면 SQL을 짤 수 밖에 없다.&lt;/li&gt;
      &lt;li&gt;관계형 DB를 쓰는 상황에서는 &lt;em&gt;SQL에 의존적인 개발을 피하기 어렵다.&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;하지만! SQL 중심적인 개발에는 여러 문제점이 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;sql-중심적인-개발의-문제점&quot;&gt;SQL 중심적인 개발의 문제점&lt;/h2&gt;
&lt;h3 id=&quot;1-지루한-코드의-무한-반복&quot;&gt;1. 지루한 코드의 무한 반복&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;CRUD의 반복&lt;/li&gt;
  &lt;li&gt;자바 객체를 SQL로, SQL을 자바 객체로 변환하는 과정의 반복&lt;/li&gt;
  &lt;li&gt;Ex)
    &lt;ul&gt;
      &lt;li&gt;회원에 나이 정보를 추가하고자 한다.&lt;/li&gt;
      &lt;li&gt;Member 클래스에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;private int age'&lt;/code&gt;를 추가한다.&lt;/li&gt;
      &lt;li&gt;INSERT, SELECT, UPDATE 등 관련된 모든 쿼리에 age 정보를 추가한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-객체-지향과-관계형-데이터베이스-간의-패러다임-불일치&quot;&gt;2. 객체 지향과 관계형 데이터베이스 간의 패러다임 불일치&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;객체 지향&lt;/strong&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;strong&gt;관계형 데이터베이스 (RDB)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;데이터를 잘 정규화해서 보관하는 것이 목표&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;패러다임이 다른 두 가지를 가지고 억지로 매핑하기 때문에 여러 가지 문제가 발생한다.
    &lt;ul&gt;
      &lt;li&gt;Object를 RDB에 넣으려고 하니까 문제가 발생한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;하지만, RDB가 인식할 수 있는 것은 SQL뿐이기 때문에 결국, Object를 SQL로 짜야한다.
    &lt;ul&gt;
      &lt;li&gt;Object -&amp;gt; [SQL 변환] -&amp;gt; RDB에 저장&lt;/li&gt;
      &lt;li&gt;[개발자 == SQL 매퍼] 라고 할만큼 SQL 작업을 너무 많이 하고 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-객체object와-관계형-데이터베이스rdb의-차이&quot;&gt;3. 객체(Object)와 관계형 데이터베이스(RDB)의 차이&lt;/h3&gt;
&lt;h4 id=&quot;1-상속&quot;&gt;1) 상속&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Object
    &lt;ul&gt;
      &lt;li&gt;상속 관계가 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RDB
    &lt;ul&gt;
      &lt;li&gt;상속 관계가 없다.&lt;/li&gt;
      &lt;li&gt;Object의 상속 관계와 유사한 물리 모델로, Table 슈퍼타입-서브타입 관계가 존재한다.&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;/images/inflearn-jpa/rdb-super-sub-relation.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Album 객체를 DB에 저장하는 과정
        &lt;ol&gt;
          &lt;li&gt;객체를 분해한다. (Album 객체는 Item의 속성을 모두 가짐)&lt;/li&gt;
          &lt;li&gt;각각 다른 테이블에 대한 INSERT 쿼리를 두 번 날린다.
            &lt;ul&gt;
              &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO ITEM ...&lt;/code&gt;&lt;/li&gt;
              &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO ALBUM ...&lt;/code&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Album 을 조회하는 과정 &lt;strong&gt;(문제!!!)&lt;/strong&gt;
        &lt;ol&gt;
          &lt;li&gt;각각의 테이블에 따른 Join SQL을 작성한다.
            &lt;ul&gt;
              &lt;li&gt;Item과 Album을 Join해서 데이터를 가져온다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;각각의 객체를 생성하고 모든 필드값을 세팅한다.
            &lt;ul&gt;
              &lt;li&gt;Item과 Album 각각 모든 필드값을 세팅한다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Movie, Book을 조회하고 싶으면 위의 과정을 또 반복해야 한다…
            &lt;ul&gt;
              &lt;li&gt;그래서! &lt;strong&gt;DB에 저장할 객체에는 상속 관계를 사용하지 않는다.&lt;/strong&gt;&lt;/li&gt;
            &lt;/ul&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;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list.add(album);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;조회: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Album album = list.get(albumId);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;다형성 활용: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item item = list.get(albumId);&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;심지어 객체 세상이기 때문에 필요하면 부모 타입으로 조회한 후 다형성으로 활용할 수도 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자바 컬렉션에 저장하면 굉장히 단순한 작업이 관계형 데이터베이스에 넣고 빼는 순간, 중간 중간의 Object와 RDB의 매핑 작업을 개발자가 직접 해줘야 하기 때문에 굉장히 번잡한 일이 된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-연관-관계&quot;&gt;2) 연관 관계&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/rdb-association-relation.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Object
    &lt;ul&gt;
      &lt;li&gt;참조(Reference)를 사용하여 연관 관계를 찾는다.
        &lt;ul&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.getTeam();&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;단방향으로만 관계가 존재한다.
        &lt;ul&gt;
          &lt;li&gt;Member -&amp;gt; Team은 가능하지만, Team -&amp;gt; Member는 불가능하다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RDB
    &lt;ul&gt;
      &lt;li&gt;외래키(FK)를 사용하여 Join 쿼리를 통해 연관 관계를 찾는다.
        &lt;ul&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JOIN ON M.TEAM_ID = T.TEAM_ID&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;양방향으로 모두 조회가 가능하다. 즉, 단방향이 존재하지 않는다.
        &lt;ul&gt;
          &lt;li&gt;Member -&amp;gt; Team 가능: MEMBER.TEAM_ID(FK)와 TEAM.ID(PK)를 Join&lt;/li&gt;
          &lt;li&gt;Team -&amp;gt; Member 가능: TEAM.ID(PK)와 MEMBER.TEAM_ID(FK)를 Join&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-데이터-타입&quot;&gt;3) 데이터 타입&lt;/h4&gt;

&lt;h4 id=&quot;4-데이터-식별-방법&quot;&gt;4) 데이터 식별 방법&lt;/h4&gt;

&lt;h3 id=&quot;4-모델링-과정에서의-문제&quot;&gt;4. 모델링 과정에서의 문제&lt;/h3&gt;
&lt;h4 id=&quot;-객체를-테이블에-맞추어-모델링&quot;&gt;# 객체를 테이블에 맞추어 모델링&lt;/h4&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// MEMBER_ID 컬럼 사용&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;teamId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// TEAM_ID FK 컬럼 사용 //**&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// USERNAME 컬럼 사용&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// TEAM_ID PK 사용&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// NAME 컬럼 사용&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;ul&gt;
  &lt;li&gt;MEMBER.TEAM_ID에 해당하는 FK를 그대로 필드에 추가한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Long teamId;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이렇게 설계된 객체를 DB에 &lt;strong&gt;&lt;em&gt;저장&lt;/em&gt;&lt;/strong&gt; 하려면,
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES ...&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;문제!: &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;객체지향스럽지 않다.&lt;/strong&gt;&lt;/span&gt;
    &lt;ul&gt;
      &lt;li&gt;Team 객체의 참조값 자체가 필드에 들어가는 것이 더 객체지향스럽다고 할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;-객체다운-모델링&quot;&gt;# 객체다운 모델링&lt;/h4&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&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;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// MEMBER_ID 컬럼 사용 &lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// USERNAME 컬럼 사용 &lt;/span&gt;
                     
    &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getTeam&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// TEAM_ID PK 사용 &lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// NAME 컬럼 사용 &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;ul&gt;
  &lt;li&gt;Team 객체의 참조값 자체를 필드에 넣는다.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Team team;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이렇게 설계된 객체를 DB에 &lt;strong&gt;&lt;em&gt;저장&lt;/em&gt;&lt;/strong&gt; 하려면,
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.getTeam().getId()&lt;/code&gt; 로 값을 얻어와 TEAM_ID에 넣는다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES ...&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Member 객체를 &lt;strong&gt;&lt;em&gt;조회&lt;/em&gt;&lt;/strong&gt; 하려면,
    &lt;ol&gt;
      &lt;li&gt;MEMBER와 TEAM을 Join해서 데이터를 한 번에 모두 가져온다.&lt;/li&gt;
      &lt;li&gt;Member와 Team에 대한 값을 각각 모두 세팅한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.setTeam(team);&lt;/code&gt;과 같이 직접 연관 관계를 맺어 준다.&lt;/li&gt;
      &lt;li&gt;해당 member 객체를 반환한다.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;문제!: &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;데이터 조회의 복잡성&lt;/strong&gt;&lt;/span&gt;
    &lt;div class=&quot;language-sql 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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&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;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;o&quot;&gt;*&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MEMBER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TEAM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt; &lt;span class=&quot;o&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;TEAM_ID&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find&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;n&quot;&gt;memberId&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;// SQL 실행 ... &lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&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;Member&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;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&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;Team&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;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;team&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;/li&gt;
  &lt;li&gt;객체다운 모델링을 자바 컬렉션에 관리하면?
    &lt;ul&gt;
      &lt;li&gt;데이터 조회의 복잡성이 사라져, 좋은 설계가 된다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;저장&lt;/em&gt;&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list.add(member);&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;조회&lt;/em&gt;&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Member member = list.get(memberId);&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Team team = member.getTeam();&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;이런 모델링을 DB에 넣는 순간, 굉장히 복잡해지며 생산성(조회 복잡)이 나빠진다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;생산성이 높은 방법?
    &lt;ul&gt;
      &lt;li&gt;Member, Team 을 모두 포함한 큰 클래스(&lt;strong&gt;Super DTO&lt;/strong&gt;)를 하나 만든다.&lt;/li&gt;
      &lt;li&gt;Super DTO 하나를 반환한다.&lt;/li&gt;
      &lt;li&gt;오히려 이런 방법이 생산성 측면에서는 좋은 방법일 수도 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;5-객체-그래프-탐색에서의-문제&quot;&gt;5. 객체 그래프 탐색에서의 문제&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/inflearn-jpa/object-graph-searching.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;객체는 자유롭게 객체 그래프(연관 관계가 있는 객체 사이)를 탐색할 수 있어야 한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.getTeam()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.getOrder().getOrderItem()&lt;/code&gt; 등 …&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;하지만, 서비스 로직에서 RDB와 연결된 데이터를 탐색할 때 객체 그래프를 탐색할 수 없다.
    &lt;ul&gt;
      &lt;li&gt;Why? &lt;strong&gt;처음 실행하는 SQL에 따라 탐색 범위가 결정&lt;/strong&gt;되기 때문이다.&lt;/li&gt;
      &lt;li&gt;Ex) 처음 SQL에서 Member와 Team을 가져왔다고 하면, Order는 가져오지 않았기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;member.getOrder()&lt;/code&gt;는 null이 된다.
        &lt;div class=&quot;language-sql 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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&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;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;o&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MEMBER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TEAM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEAM_ID&lt;/span&gt; &lt;span class=&quot;o&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;TEAM_ID&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&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;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// OK&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;문제점&quot;&gt;문제점&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;문제!: &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;Entity 신뢰 문제&lt;/strong&gt;&lt;/span&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemberService&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&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;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
      &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&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;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDelivery&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;o&quot;&gt;}&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;/li&gt;
  &lt;li&gt;Ex) 개발자 A가 DAO를 구현하고 개발자 B가 위의 서비스 로직(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process()&lt;/code&gt;)을 구현했을 때,
    &lt;ul&gt;
      &lt;li&gt;개발자 B는 DAO에서 반환한 엔티티를 신뢰하고 사용할 수 없다.&lt;/li&gt;
      &lt;li&gt;DAO에서 직접 어떤 쿼리를 날렸는지 확인하지 않는 이상, 알 수가 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이와 같은 &lt;strong&gt;계층형 아키텍처&lt;/strong&gt;(&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%8B%A4%EC%B8%B5_%EA%B5%AC%EC%A1%B0&quot;&gt;Layered 아키텍처&lt;/a&gt;)에서는 그 다음 계층에서 신뢰하고 사용해야 하는데, 여기에서는 엔티티를 신뢰할 수 없는 문제가 발생하게 된다.
    &lt;ul&gt;
      &lt;li&gt;물리적으로는 Service Layer, DAO Layer 등으로 계층이 분리되어 있지만,&lt;/li&gt;
      &lt;li&gt;논리적으로는 DAO 내부 코드를 직접 확인한 후에 엔티티를 제대로 가져오는지 신뢰를 할 수 있기 때문에 각 계층이 엮여 있는 상태라고 할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;해결책&quot;&gt;해결책?&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;그렇다고 모든 객체를 미리 로딩할 수는 없다.
    &lt;ul&gt;
      &lt;li&gt;대안: 여러 상황에 따른 동일한 회원 조회 메서드를 여러 개 만들어 둔다.&lt;/li&gt;
      &lt;li&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;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Member만 조회&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMemberWithTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Member와 Team 조회&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMemberWithOrderWithDelivery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Member, Order, Delivery 조회 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이렇게 SQL을 직접 다루면 계층형 아키텍처(Layered 아키텍처)에서 진정한 의미의 &lt;strong&gt;계층 분할이 어렵다.&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;물리적으로는 계층이 나누어져 있지만, 논리적으로는 굉장히 강결합되어 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;6-비교하기-에서의-차이&quot;&gt;6. “비교하기” 에서의 차이&lt;/h3&gt;
&lt;h4 id=&quot;-일반적인-sql을-사용하는-경우&quot;&gt;# 일반적인 SQL을 사용하는 경우&lt;/h4&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;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MemberDAO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getMember&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;n&quot;&gt;memberId&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;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SELECT * FROM MEMBER WHERE MEMBER_ID = ?&quot;&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;// JDBC API, SQL 실행 &lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Member&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;식별자가 같아도 DAO의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getMember()&lt;/code&gt;에서
    &lt;ul&gt;
      &lt;li&gt;각각에 대해서 SELECT Query를 날리고 (두 번 날림)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new Member()&lt;/code&gt;로 객체를 생성하기 때문에 당연히 다르다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;-자바-컬렉션에서-조회하는-경우&quot;&gt;# 자바 컬렉션에서 조회하는 경우&lt;/h4&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;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&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;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&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;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;member1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member2&lt;/span&gt;&lt;span class=&quot;o&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;h2 id=&quot;마무리&quot;&gt;마무리&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;객체답게 모델링 할수록 매핑 작업만 늘어난다.&lt;/li&gt;
  &lt;li&gt;객체를 자바 컬렉션에 저장하고 불러오듯이 DB에 저장할 수는 없을까?
    &lt;ul&gt;
      &lt;li&gt;이 고민의 결과가 바로 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;JPA(Java Persistence API)&lt;/strong&gt;&lt;/span&gt; 이다!!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;ORM의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/01/orm.html&quot;&gt;ORM이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JPA의 개념에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html&quot;&gt;JPA란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic#&quot;&gt;인프런 강의 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sat, 03 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/08/03/reason-why-use-jpa.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/08/03/reason-why-use-jpa.html</guid>
        
        <category>inflearn</category>
        
        <category>jpa</category>
        
        
      </item>
    
      <item>
        <title>[IntelliJ] intellij 유용한 단축키 정리</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.inflearn.com/course/intellij-guide/lecture/13200&quot;&gt;인프런 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;코드 Edit&lt;/li&gt;
    &lt;li&gt;포커스&lt;/li&gt;
    &lt;li&gt;검색&lt;/li&gt;
    &lt;li&gt;자동완성&lt;/li&gt;
    &lt;li&gt;리팩토링&lt;/li&gt;
    &lt;li&gt;디버깅&lt;/li&gt;
    &lt;li&gt;Git&lt;/li&gt;
    &lt;li&gt;플러그인&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt; &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;계속해서 추가할 예정입니다!&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;기본-단축키&quot;&gt;기본 단축키&lt;/h2&gt;
&lt;h3 id=&quot;디렉터리-패키지-클래스-등-생성-목록-보기&quot;&gt;디렉터리, 패키지, 클래스 등 생성 목록 보기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;MacOS: Cmd + n&lt;/li&gt;
  &lt;li&gt;Win/Linux: Alt + Insert&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;코드-edit&quot;&gt;코드 Edit&lt;/h2&gt;
&lt;h3 id=&quot;main-method-생성-및-실행&quot;&gt;Main method 생성 및 실행&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;메인 메서드 선언
    &lt;ul&gt;
      &lt;li&gt;live template 이용: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;psvm&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;(live template은 아래 참고)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;메인 메서드 실행
    &lt;ol&gt;
      &lt;li&gt;좌측 실행 버튼&lt;/li&gt;
      &lt;li&gt;단축키
        &lt;ul&gt;
          &lt;li&gt;&lt;em&gt;현재 Focus&lt;/em&gt; 가 해당 메서드에 있어야 함&lt;/li&gt;
        &lt;/ul&gt;
        &lt;ul&gt;
          &lt;li&gt;MacOS: Ctrl + Shift + r&lt;/li&gt;
          &lt;li&gt;Win/Linux: Ctrl + Shift + F10
      - &lt;em&gt;이전 실행문&lt;/em&gt; 재실행 (우측 상단에 실행문 목록 확인 가능)&lt;/li&gt;
          &lt;li&gt;MacOS: Ctrl + r&lt;/li&gt;
          &lt;li&gt;Win/Linux: Shift + F10&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;라인-수정하기&quot;&gt;라인 수정하기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;라인 복제하기
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + d&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + d&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;라인 삭제하기
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + 백스페이스&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + y&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;문자열 라인 합치기
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + Shift + j&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + j&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;라인 단위로 옮기기
    &lt;ul&gt;
      &lt;li&gt;1) 문법에 관계 없이 라인 이동
        &lt;ul&gt;
          &lt;li&gt;MacOS: Opt + Shift +  ↑↓&lt;/li&gt;
          &lt;li&gt;Win/Linux: Alt + Shift +  ↑↓&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;2) 구문 안에서만 라인 이동 (메서드를 벗어날 수 없음)
        &lt;ul&gt;
          &lt;li&gt;MacOS: Cmd + Shift + ↑↓&lt;/li&gt;
          &lt;li&gt;Win/Linux: Ctrl + Shift + ↑↓&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Element 단위로 옮기기
    &lt;ul&gt;
      &lt;li&gt;Ex. html, xml 등의 규격이 정해진 마크업 언어에서 활용&lt;/li&gt;
      &lt;li&gt;MacOS: Cmd + Opt + Shift + ←→&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + Shift + ←→&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;코드-즉시-보기&quot;&gt;코드 즉시 보기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;인자값 즉시 보기 (Parameter Info)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + p&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + p&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;코드 구현부 즉시 보기 (Quick Definition)
    &lt;ul&gt;
      &lt;li&gt;클래스- 클래스 전체 코드&lt;/li&gt;
      &lt;li&gt;인스턴스- 인스턴스 생성 코드&lt;/li&gt;
      &lt;li&gt;메서드- 메서드 정의 코드&lt;/li&gt;
      &lt;li&gt;MacOS: Opt + Space&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + i&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Doc 즉시 보기 (Quick Documentation)
    &lt;ul&gt;
      &lt;li&gt;MacOS: F1&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + q&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;포커스&quot;&gt;포커스&lt;/h2&gt;
&lt;h3 id=&quot;포커스-에디터&quot;&gt;포커스 에디터&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;단어별 이동
    &lt;ul&gt;
      &lt;li&gt;MacOS: Opt + ←→&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + ←→&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;단어별 선택 (Move Caret to Next Word with Selection)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Opt + Shift + ←→&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + ←→&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;라인 첫/끝 이동
    &lt;ul&gt;
      &lt;li&gt;MacOS: fn +  ←→&lt;/li&gt;
      &lt;li&gt;Win/Linux: Home, End&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;라인 전체 선택
    &lt;ul&gt;
      &lt;li&gt;MacOS: fn + Shift +  ←→&lt;/li&gt;
      &lt;li&gt;Win/Linux: Shift + Home, End&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Page Up/Down
    &lt;ul&gt;
      &lt;li&gt;MacOS: fn + ↑↓&lt;/li&gt;
      &lt;li&gt;Win/Linux: Page Up, Page Down&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;포커스-특수키&quot;&gt;포커스 특수키&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;포커스 범위 한 단계씩 늘리기 (Extend Selection)
    &lt;ul&gt;
      &lt;li&gt;해당 커서의 단어 포커스하기&lt;/li&gt;
      &lt;li&gt;MacOS: Opt + ↑↓&lt;/li&gt;
      &lt;li&gt;Win/Linux
        &lt;ul&gt;
          &lt;li&gt;위: Ctrl + w&lt;/li&gt;
          &lt;li&gt;아래: Ctrl + Shift + w&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;포커스 뒤로/앞으로 가기 (Navigate -&amp;gt; Back/Forward)
    &lt;ul&gt;
      &lt;li&gt;이전 커서가 있던 화면으로 돌아갈 때 유용&lt;/li&gt;
      &lt;li&gt;클래스 이동도 가능&lt;/li&gt;
      &lt;li&gt;MacOS: Cmd + [ 또는 ]&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + ←→&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;멀티 포커스 (Clone Caret Below)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Opt + Opt + ↓ (Opt 누른 상태)&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Ctrl + ↓ (Ctrl 누른 상태)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;오류 라인으로 자동 포커스 (Navigate -&amp;gt; Next Highlighted Error)
    &lt;ul&gt;
      &lt;li&gt;MacOS: F2&lt;/li&gt;
      &lt;li&gt;Win/Linux: F2&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;검색&quot;&gt;검색&lt;/h2&gt;
&lt;h3 id=&quot;검색-텍스트&quot;&gt;검색 텍스트&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;현재 파일에서 검색 (Find)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + f&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + f&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;현재 파일에서 교체 (Replace)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + r&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + r&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;전체에서 검색 (Find in Path)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + f&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + f&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;전체에서 교체 (Replace in Path)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + r&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + r&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;정규표현식으로 검색, 교체
    &lt;ul&gt;
      &lt;li&gt;[Find/Replace] -&amp;gt; Regex 체크&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;검색-기타&quot;&gt;검색 기타&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;파일 검색 (Navigate -&amp;gt; File)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + o&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + n&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;메서드 검색 (Navigate -&amp;gt; Symbol)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Opt + o&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + Alt + n&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Action 검색&lt;/strong&gt; (Find Action: Enter action or option name)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + a&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + a&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;최근 열었던 파일 목록 보기 (Recent Files)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + e&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + e&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;최근 수정한 파일 목록 보기 (Recently Changed Files)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + e&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + e&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;자동완성&quot;&gt;자동완성&lt;/h2&gt;
&lt;h3 id=&quot;자동완성-1&quot;&gt;자동완성&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;기본 자동완성 (Completion -&amp;gt; Basic)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + Space&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Space&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;스마트 자동완성 (Completion -&amp;gt; SmartType)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + Shift + Space&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + Space&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;static method 자동완성
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + Space + Space&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Space + Space&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;getter/setter/생성자 자동완성 (Generate)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + n&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + Insert&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Override 메서드 자동완성 (Implement Methods)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + i&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + i&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;live-template-code-template&quot;&gt;Live Template (Code Template)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;live template 목록 확인하기 (Insert Live Template)
    &lt;ul&gt;
      &lt;li&gt;[Find Action] -&amp;gt; Live Templates 입력&lt;/li&gt;
      &lt;li&gt;MacOS: Cmd + j&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + j&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자주 사용하는 live template 예시
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;psvm&lt;/code&gt;&lt;/strong&gt;: 메인메서드 선언&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sout&lt;/code&gt;&lt;/strong&gt;: System.out.println(); 자동 생성&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;나만의 live template 추가하기
    &lt;ol&gt;
      &lt;li&gt;[Find Action] -&amp;gt; Live Templates 입력&lt;/li&gt;
      &lt;li&gt;other 선택 -&amp;gt; “+” 버튼 -&amp;gt; Live Template&lt;/li&gt;
      &lt;li&gt;Abbreviation(축약어)
        &lt;ul&gt;
          &lt;li&gt;Ex. ent&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Description(설명)
        &lt;ul&gt;
          &lt;li&gt;Ex. Entity Class Header&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Template text(텍스트)
        &lt;ul&gt;
          &lt;li&gt;아래 예시&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Error(No applicable contexts yet.)에서 Define 클릭
        &lt;ul&gt;
          &lt;li&gt;Ex. Java 선택&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Apply &amp;amp; OK&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&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;c1&quot;&gt;// ORM에서의 반복적인 코드 (live template로 설정)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Getter&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@NoArgsConstructor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AccessLevel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PROOTECTED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Entity&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/** Entity Class */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Id&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@GeneratedValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenerationType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IDENTITY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;h2 id=&quot;리팩토링&quot;&gt;리팩토링&lt;/h2&gt;
&lt;h3 id=&quot;리팩토링-extract&quot;&gt;리팩토링 Extract&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;변수 추출하기 (Extract -&amp;gt; Variable)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Opt + v&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + v&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;파라미터 추출하기 (Extract -&amp;gt; Parameter)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Opt + p&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + p&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;메서드 추출하기&lt;/strong&gt; (Extract -&amp;gt; Method)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Opt + m&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + m&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이너클래스 추출하기
    &lt;ul&gt;
      &lt;li&gt;MacOS: F6&lt;/li&gt;
      &lt;li&gt;Win/Linux: F6&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;리팩토링-기타&quot;&gt;리팩토링 기타&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;이름 일괄 변경하기 (Rename)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Shift + F6&lt;/li&gt;
      &lt;li&gt;Win/Linux: Shift + F6&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;타입 일괄 변경하기 (Type Migration)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + F6&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + F6&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Import 정리하기 (Optimize Imports)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + Opt + o&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + o&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;자동 설정:&lt;/em&gt; [Find Action] -&amp;gt; Optimize imports on 입력 -&amp;gt; “Auto import: …”&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;코드 자동 정렬하기 (Reformat Code)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Opt + l&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Alt + l&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;디버깅&quot;&gt;디버깅&lt;/h2&gt;
&lt;h3 id=&quot;디버깅-1&quot;&gt;디버깅&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Break Point 걸기 (Toggle Line Breakpoint)
    &lt;ul&gt;
      &lt;li&gt;해당 라인 number 옆 클릭&lt;/li&gt;
      &lt;li&gt;MacOS: Cmd + F8&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + F8&lt;/li&gt;
      &lt;li&gt;Break Point의 라인은 아직 실행하기 전 상태이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Conditional Break Point
    &lt;ul&gt;
      &lt;li&gt;반복문에서 특정값을 가지고 있는 객체가 나왔을 때만 멈추고자 할 때 유용&lt;/li&gt;
      &lt;li&gt;Break Point (빨간원) 우클릭 -&amp;gt; 조건 입력
        &lt;ul&gt;
          &lt;li&gt;Ex. “HEEE”.equals(user.name)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Debug 모드로 실행하기 - 즉시 실행 (Debug)
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;현재 Focus&lt;/em&gt; 가 해당 메서드에 있어야 함&lt;/li&gt;
      &lt;li&gt;좌측 디버그 실행 버튼&lt;/li&gt;
      &lt;li&gt;MacOS: Ctrl + Shift + d&lt;/li&gt;
      &lt;li&gt;Win/Linux: 없음 (커스텀해서 사용하거나 마우스 이용)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Debug 모드로 실행하기 - 이전 실행
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;이전 실행문&lt;/em&gt; 재실행 (우측 상단에 실행문 목록 확인 가능)&lt;/li&gt;
      &lt;li&gt;MacOS: Ctrl + d&lt;/li&gt;
      &lt;li&gt;Win/Linux: Shift + F9&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;breaking-상태에서의-기능&quot;&gt;Breaking 상태에서의 기능&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/etc/intellij-shortkey-debug.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Resume&lt;/strong&gt; (다음 Break Point로 넘어가기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Opt + Cmd + r&lt;/li&gt;
      &lt;li&gt;Win/Linux: F9&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;mark&gt;참고&lt;/mark&gt; Debugger 탭 설명
    &lt;ul&gt;
      &lt;li&gt;Debugger 탭 좌측 창 - Call Stack
        &lt;ul&gt;
          &lt;li&gt;현재 Break Point로 넘어오기까지 실행한 메서드 목록&lt;/li&gt;
          &lt;li&gt;오픈 소스 코드를 분석할 때 유용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Debugger 탭 우측 창 - Variables
        &lt;ul&gt;
          &lt;li&gt;현재 Break Point에서 볼 수 있는 변수값 목록&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Step Over (다음 라인으로 넘어가기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: F8&lt;/li&gt;
      &lt;li&gt;Win/Linux: F8&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Step Into (해당 라인 안(다음 메서드)으로 들어가기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: F7&lt;/li&gt;
      &lt;li&gt;Win/Linux: F7&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Step Out (현재 포커스를 밖으로 빼기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Shift + F8&lt;/li&gt;
      &lt;li&gt;Win/Linux: Shift + F8&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Evaluate Expression (현재 Breaking 상태에서 즉시 코드 실행하기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Opt + F8&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + F8&lt;/li&gt;
      &lt;li&gt;데이터가 잘 들어갔는지 확인할 때 유용&lt;/li&gt;
      &lt;li&gt;켤 때마다 초기화 - 단발성 코드를 실행할 때 유용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Watch (Breaking 이후의 코드 변경 확인하기)
    &lt;ul&gt;
      &lt;li&gt;MacOS: 없음&lt;/li&gt;
      &lt;li&gt;Win/Linux: 없음&lt;/li&gt;
      &lt;li&gt;다음 Break Point 전까지 확인하고 싶은 값을 계속 주시하고자할 때 유용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;git--github&quot;&gt;Git &amp;amp; Github&lt;/h2&gt;
&lt;h3 id=&quot;git-기본-기본-기능-사용하기&quot;&gt;Git 기본 기본 기능 사용하기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Git View On
    &lt;ul&gt;
      &lt;li&gt;View 탭 -&amp;gt; Tool Windows -&amp;gt; Version Control&lt;/li&gt;
      &lt;li&gt;MacOS: Cmd + 9&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + 9&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Git Option Popup (VCS Operations Popup)
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + v&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + `(Back Quote)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Git History
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + v =&amp;gt; 4&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + ` =&amp;gt; 4&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Branch
    &lt;ul&gt;
      &lt;li&gt;MacOS: Ctrl + v =&amp;gt; 7&lt;/li&gt;
      &lt;li&gt;Win/Linux: Alt + ` =&amp;gt; 7&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Commit
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + k&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + k&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Push
    &lt;ul&gt;
      &lt;li&gt;MacOS: Cmd + Shift + k&lt;/li&gt;
      &lt;li&gt;Win/Linux: Ctrl + Shift + k&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Pull
    &lt;ul&gt;
      &lt;li&gt;MacOS: [Find Action] =&amp;gt; git pull 검색&lt;/li&gt;
      &lt;li&gt;Win/Linux: [Find Action] =&amp;gt; git pull 검색&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;플러그인&quot;&gt;플러그인&lt;/h2&gt;
&lt;h3 id=&quot;플러그인-설치-방법&quot;&gt;플러그인 설치 방법&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;[Find Action] -&amp;gt; plugins 입력 -&amp;gt; Preferences/Settings의 Plugins 선택&lt;/li&gt;
  &lt;li&gt;Browse repositories… 클릭&lt;/li&gt;
  &lt;li&gt;Sort by: Downloads 로 설정&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;추천-플러그인&quot;&gt;추천 플러그인&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;presentation assistant&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;다른 OS에서 해당 단축키가 어떤 것인지 알려준다.&lt;/li&gt;
      &lt;li&gt;발표/시연용으로 사용할 때 유용하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;.gitignore&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;자동완성 기능을 제공한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;BashSupport&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;실행 파일에 대한 여러 기능을 제공한다.&lt;/li&gt;
      &lt;li&gt;Cf. 실행 권한 변경 후 실행 가능
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x app.sh&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Material Theme UI&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;추천 테마&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;jojoldu Translation&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;영문 코드를 한글로, 한글을 영문으로 번역해주는 기능을 제공한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;Vim에서 유용한 단축키에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/05/14/vim-shortkey.html&quot;&gt;Vim 유용한 단축키 정리&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/intellij-guide/lecture/13200&quot;&gt;https://www.inflearn.com/course/intellij-guide/lecture/13200&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.yasir252.com/software/programming-tools/jetbrains-intellij-full-version/&quot;&gt;이미지 참고&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 21 May 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/05/21/intellij-shortkey.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/05/21/intellij-shortkey.html</guid>
        
        <category>intellij</category>
        
        <category>shortkey</category>
        
        <category>hotkey</category>
        
        <category>단축키</category>
        
        
      </item>
    
      <item>
        <title>[VIM] vim 유용한 단축키 정리</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;vim의 단축키 사용법에 대해 이해한다.
      &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;
        &lt;li&gt;기타 (매크로, 이어 붙이기, 취소하기/되돌리기 및 들여쓰기/내어쓰기, 대소문자 전환, 숫자 증감, 창 열기/탭 이동 등 )&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/etc/vim-shortkey-keyboard.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;이동&quot;&gt;이동&lt;/h2&gt;
&lt;h3 id=&quot;기본-이동&quot;&gt;기본 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;h, j, k, l:&lt;/strong&gt; 좌,하,상,우 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;-:&lt;/strong&gt; 줄의 처음 위치로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;gg:&lt;/strong&gt; 맨 위로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[shift + g]:&lt;/strong&gt; 맨 아래로 커서 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;단어-단위로-이동&quot;&gt;단어 단위로 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;w:&lt;/strong&gt; 단어의 시작 위치로 커서 이동 (forward 방향)
    &lt;ul&gt;
      &lt;li&gt;Ex. 3w: 세 단어 앞으로 커서 이동&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;e:&lt;/strong&gt; 단어의 마지막 위치로 커서 이동 (forward 방향)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;b:&lt;/strong&gt; 단어의 시작 위치로 커서 이동 (backward 방향)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ge:&lt;/strong&gt; 단어의 마지막 위치로 커서 이동 (backward 방향)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;한-문장-내에서의-이동&quot;&gt;한 문장 내에서의 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;0(숫자):&lt;/strong&gt; 라인 맨 앞으로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;^:&lt;/strong&gt; 문장 맨 앞으로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;$:&lt;/strong&gt; 문장 맨 뒤로 커서 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;대략적인-위치로-이동-현재-보이는-페이지-기준&quot;&gt;대략적인 위치로 이동 (현재 보이는 페이지 기준)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[shift + h]:&lt;/strong&gt; 현재 보이는 페이지를 기준으로 맨 위로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[shift + m]:&lt;/strong&gt; 현재 보이는 페이지를 기준으로 중간 라인으로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[shift + l]:&lt;/strong&gt; 현재 보이는 페이지를 기준으로 맨 아래로 커서 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;페이지-이동&quot;&gt;페이지 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl+ f]:&lt;/strong&gt; 다음 페이지의 첫 줄로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl+ b]:&lt;/strong&gt; 다음 페이지의 마지막 줄로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl+ d]:&lt;/strong&gt; 페이지의 절반 크기만큼 아래로 커서 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl+ u]:&lt;/strong&gt; 페이지의 절반 크기만큼 위로 커서 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;원하는-줄-번호로-한-번에-이동&quot;&gt;원하는 줄 번호로 한 번에 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;줄 번호 설정 및 해지
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;[: + set number]:&lt;/strong&gt; 줄 번호 설정&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;[: + set nonumber]:&lt;/strong&gt; 줄 번호 설정&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;방법1
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;[esc]&lt;/strong&gt; 를 눌러 표준 모드로 진입&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;[:]&lt;/strong&gt; 를 누른 후 원하는 &lt;strong&gt;[줄 번호]&lt;/strong&gt; 입력&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;방법2
    &lt;ol&gt;
      &lt;li&gt;&lt;strong&gt;[esc]&lt;/strong&gt; 를 눌러 표준 모드로 진입&lt;/li&gt;
      &lt;li&gt;원하는 &lt;strong&gt;[줄 번호]&lt;/strong&gt; 입력&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;[shift + g]&lt;/strong&gt; 입력&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;컬리-블레이스-curly-brace-을-기준으로-이동&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;(컬리 블레이스, Curly Brace) 을 기준으로 이동&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;]]:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;로 커서 이동 (forward 방향)
    &lt;ul&gt;
      &lt;li&gt;없으면 페이지의 맨 아래로 커서 이동&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;은 가장 상위의 블록을 감싸고 있는 문자만 찾는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[[:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;로 커서 이동 (backward 방향)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;][:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt;로 커서 이동 (forward 방향)
    &lt;ul&gt;
      &lt;li&gt;없으면 페이지의 맨 위로 커서 이동&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt;은 가장 상위의 블록을 감싸고 있는 문자만 찾는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[]:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt;로 커서 이동 (backward 방향)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;%:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;에서 현재 괄호의 짝으로 커서 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;편집&quot;&gt;편집&lt;/h2&gt;
&lt;h3 id=&quot;삽입-관련-단축키-입력-가능한-상태로-변경&quot;&gt;삽입 관련 단축키 (입력 가능한 상태로 변경)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;i:&lt;/strong&gt; 현재 커서가 위치한 문자의 앞에 Insert 하기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;I:&lt;/strong&gt; 현재 커서가 위치한 줄 맨 앞에 Insert 하기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;a:&lt;/strong&gt; 현재 커서가 위치한 문자의 뒤에 Insert 하기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; 현재 커서가 위치한 줄 맨 뒤에 Insert 하기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;O:&lt;/strong&gt; 현재 커서가 위치한 줄 바로 윗줄에 Insert 하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;o:&lt;/strong&gt; 현재 커서가 위치한 줄 바로 아랫줄에 Insert 하기&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;삭제잘라내기-및-수정-관련-단축키&quot;&gt;삭제/잘라내기 및 수정 관련 단축키&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;dd:&lt;/strong&gt; 커서가 위치한 줄 잘라내기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;dw:&lt;/strong&gt; 커서가 위치한 곳부터 단어의 마지막까지 잘라내기
    &lt;ul&gt;
      &lt;li&gt;Ex. &lt;strong&gt;숫자 + dd:&lt;/strong&gt; 커서가 위치한 줄부터 숫자에 해당하는 수만큼의 줄 잘라내기&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;[shift + d]:&lt;/strong&gt; 현재 커서의 위치부터 줄의 끝까지 잘라내기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;x:&lt;/strong&gt; 커서가 위치한 문자 잘라내기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;[shift + x]:&lt;/strong&gt; 커서가 위치한 문자 바로 앞에 있는 문자 잘라내기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;s:&lt;/strong&gt; 커서가 위치한 문자 잘라내고 Insert 하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;cc&lt;/strong&gt; 또는 &lt;strong&gt;[shift + s]&lt;/strong&gt;: 커서가 위치한 줄 전체 잘라내고 Insert 하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;cw:&lt;/strong&gt; 커서가 위치한 곳부터 단어의 마지막까지 잘라내고 Insert 하기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;[shift + c]:&lt;/strong&gt; 현재 커서의 위치부터 줄의 끝까지 잘라내고 Insert 하기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[r + 변경할 문자]:&lt;/strong&gt; 커서가 위치한 문자 하나 수정하기
    &lt;ul&gt;
      &lt;li&gt;Ex. 4rx: 현재 커서 이후 4개의 글자를 “x”로 수정한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;복사붙여넣기-관련-단축키&quot;&gt;복사/붙여넣기 관련 단축키&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;yl:&lt;/strong&gt; 현재 커서가 위치한 문자 하나만 복사하기
    &lt;ul&gt;
      &lt;li&gt;Ex. 3yl: 현재 커서 이후 3개의 문자를 복사한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;yy:&lt;/strong&gt; 현재 커서가 위치한 줄 복사하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;yw:&lt;/strong&gt; 현재 커서의 위치부터 단어가 끝나는 위치까지 복사하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;y:&lt;/strong&gt; 블럭 단위로 체크한 내용(비주얼 모드 이용) 복사하기 - 한 문자만 복사 X
    &lt;ul&gt;
      &lt;li&gt;Ex. &lt;strong&gt;숫자 + y:&lt;/strong&gt; 커서가 위치한 줄부터 숫자에 해당하는 수만큼의 줄 복사하기&lt;/li&gt;
      &lt;li&gt;Ex. &lt;strong&gt;y$:&lt;/strong&gt; 커서가 위치한 곳부터 줄의 마지막까지 복사하기&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;p:&lt;/strong&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;strong&gt;[shift + p]:&lt;/strong&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;strong&gt;숫자 + p:&lt;/strong&gt; 해당 숫자 만큼 붙여넣기를 반복하기&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;선택&quot;&gt;선택&lt;/h2&gt;
&lt;h3 id=&quot;한-줄-선택&quot;&gt;한 줄 선택&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[shift + v]:&lt;/strong&gt; 라인 단위로 블럭지정이 가능하다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;단어-단위로-여러-줄-선택&quot;&gt;단어 단위로 여러 줄 선택&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;[esc]&lt;/strong&gt; 를 눌러 표준 모드로 진입&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;비주얼 모드&quot;&gt;v&lt;/a&gt;&lt;/strong&gt; 를 눌러 여러 줄을 선택할 수 있는 상태를 만든다.
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;v:&lt;/strong&gt; 단어 단위&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;[shift + v]:&lt;/strong&gt; 라인 단위&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;멀티-포커스&quot;&gt;멀티 포커스&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl + v]:&lt;/strong&gt; 블럭 단위로 여러 줄 선택. 즉, 사각형의 블럭지정이 가능하다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;검색&quot;&gt;검색&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;/ + 찾을 단어 + Enter:&lt;/strong&gt; 문서에서 단어 찾기
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;n 또는 *:&lt;/strong&gt; 다음 찾기 (forward 방향)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;N 또는 #:&lt;/strong&gt; 이전 찾기 (backward 방향)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&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;h3 id=&quot;다음-줄을-현재-커서가-있는-줄의-끝으로-이어-붙이기&quot;&gt;다음 줄을 현재 커서가 있는 줄의 끝으로 이어 붙이기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[shift + j]:&lt;/strong&gt; 다음 줄을 현재 커서가 있는 줄의 끝으로 이어 붙인다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;취소하기되돌리기-및-들여쓰기내어쓰기&quot;&gt;취소하기/되돌리기 및 들여쓰기/내어쓰기&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;u:&lt;/strong&gt; Undo, 이전으로 취소하기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl + r]:&lt;/strong&gt; Redo, 취소한 것을 다시 되돌리기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&amp;gt; 2번 클릭:&lt;/strong&gt; 들여쓰기
&lt;!-- - **[: + set ai]:** 자동 indent  --&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;&amp;gt;}:&lt;/strong&gt; 한 문단 전체를 들여쓰기&lt;/li&gt;
      &lt;li&gt;Ex. &lt;strong&gt;2»:&lt;/strong&gt; 2번 들여쓰기&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&amp;lt; 2번 클릭:&lt;/strong&gt; 내어쓰기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;.:&lt;/strong&gt; - 이전 명령어를 다시 실행&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;대소문자-전환&quot;&gt;대소문자 전환&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[shift + ~]:&lt;/strong&gt; 현재 커서가 위치한 문자의 대소문자를 변경한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;숫자-증감&quot;&gt;숫자 증감&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl + a]:&lt;/strong&gt; 현재 커서가 위치한 하나의 문자가 숫자라면 해당 명령어로 숫자를 증가시킬 수 있다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[ctrl + x]:&lt;/strong&gt; 현재 커서가 위치한 하나의 문자가 숫자라면 해당 명령어로 숫자를 감소시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;창-열기탭-이동-등&quot;&gt;창 열기/탭 이동 등&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;[: + vs]:&lt;/strong&gt; 현재의 창을 세로로 분할된 창으로 하나 더 열기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[: + new]:&lt;/strong&gt; 새 창을 현재의 창 아래(세로로)에 분할된 창으로 열기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[: + tabnew]:&lt;/strong&gt; 새 창을 현재의 창과 같은 위치에 열기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;[ctrl + w] 2번 클릭:&lt;/strong&gt; 분할 창 간에 이동&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[gt]:&lt;/strong&gt; 오른쪽 탭으로 이동&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;[gT]:&lt;/strong&gt; 왼쪽 탭으로 이동&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;코드-형식-관련&quot;&gt;코드 형식 관련&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;zc:&lt;/strong&gt; 코드 접기 (fold)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;zM:&lt;/strong&gt; 코드 모두 접기 (fold)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;zo:&lt;/strong&gt; 접힌 코드 펼치기&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;zR:&lt;/strong&gt; 접힌 코드 모두 펼치기&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;zd:&lt;/strong&gt; fold 지우기&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;zD:&lt;/strong&gt; 모든 fold 지우기&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;IntelliJ에서 유용한 단축키에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/05/21/intellij-shortkey.html&quot;&gt;IntelliJ 유용한 단축키 정리&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://blog.outsider.ne.kr/540&quot;&gt;https://blog.outsider.ne.kr/540&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://vim.rtorr.com/lang/ko&quot;&gt;https://vim.rtorr.com/lang/ko&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://egloos.zum.com/kwon37xi/v/1501256&quot;&gt;http://egloos.zum.com/kwon37xi/v/1501256&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://vim.rtorr.com/lang/ko&quot;&gt;https://vim.rtorr.com/lang/ko&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://devanix.tistory.com/170&quot;&gt;https://devanix.tistory.com/170&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://ickhyun82.blogspot.com/2012/02/vi.html&quot;&gt;http://ickhyun82.blogspot.com/2012/02/vi.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.vimgolf.com/&quot;&gt;vimgolf - vi 학습 프로그램&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 14 May 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/05/14/vim-shortkey.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/05/14/vim-shortkey.html</guid>
        
        <category>vim</category>
        
        <category>shortkey</category>
        
        <category>hotkey</category>
        
        <category>단축키</category>
        
        
      </item>
    
      <item>
        <title>[DB] SQL문 기본 문법 - 데이터 추가, 삭제, 갱신</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;INSERT 명령문 (SQL 기본 문법)&lt;/li&gt;
    &lt;li&gt;UPDATE 명령문 (SQL 기본 문법)&lt;/li&gt;
    &lt;li&gt;DELETE 명령문 (SQL 기본 문법)&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;insert-명령문-sql의-dml&quot;&gt;INSERT 명령문 (SQL의 DML)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;DB의 테이블에 행 추가
    &lt;ul&gt;
      &lt;li&gt;웹 페이지에서 ‘신규등록’이나 ‘추가’와 같은 버튼을 클릭했을 때 처리되는 데이터 추가 기능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SELECT 명령의 경우 실행하면 그 결과가 클라이언트에게 반환되자만, INSERT 명령은 데이터가 클라이언트에서 서버로 전송되므로 반환되는 결과가 없다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;기본 사용 예시&lt;/strong&gt;
    &lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;VALUES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&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;err&quot;&gt;값&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;VALUES&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;s1&quot;&gt;'HEEE'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'2019-04-27'&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;/li&gt;
  &lt;li&gt;&lt;strong&gt;값을 저장할 열 지정&lt;/strong&gt;
    &lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&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;err&quot;&gt;열&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;VALUES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&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;err&quot;&gt;값&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&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;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;VALUES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'HEEE2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&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;/li&gt;
  &lt;li&gt;&lt;strong&gt;NOT NULL 제약&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;NULL을 허용하고 싶지 않은 열에 NOT NULL 제약을 걸어둔다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DEFAULT&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;명시적으로 값을 지정하지 않았을 경우 사용하는 초깃값을 말한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DESC 테이블명&lt;/code&gt;으로 테이블의 열 구성을 살펴보면 Default라는 항목에서 초깃값 확인 가능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;delete-명령문-sql의-dml&quot;&gt;DELETE 명령문 (SQL의 DML)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;DB의 테이블에서 행을 삭제&lt;/li&gt;
  &lt;li&gt;삭제는 행 단위로 수행되며, 열을 지정하여 해당 열만 삭제할 수는 없다.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;DELETE 명령을 실행할 때는 재확인을 위한 대화창 같은 것이 표시되지 않기 때문에 주의해야 한다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;기본 사용 예시&lt;/strong&gt;
    &lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DELETE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&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-sql 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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블의&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;모든&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;데이터&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;삭제&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DELETE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&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;sample&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블의&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;인&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;삭제&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DELETE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;/li&gt;
  &lt;li&gt;&lt;strong&gt;물리삭제와 논리삭제&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;DB에서 데이터를 삭제하는 방법은 용도에 따라 크게 ‘물리삭제’와 ‘논리삭제’로 나뉜다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;물리삭제&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;SQL의 DELETE 명령을 사용해 직접 데이터를 삭제하는 것&lt;/li&gt;
          &lt;li&gt;Ex) SNS 서비스에서의 사용자 탈퇴&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;논리삭제&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;테이블에 ‘삭제 플래그’를 두어 행을 삭제하는 대신, SQL의 UPDATE 명령을 사용해 해당 플래그의 값을 유효하게 갱신해두는 것&lt;/li&gt;
          &lt;li&gt;장점: 삭제 되기 전의 상태로 간단히 되돌릴 수 있다.&lt;/li&gt;
          &lt;li&gt;단점: 삭제해도 DB의 저장공간이 늘어나지 않는다. 이로 인해 DB 크기가 증가하여 검색속도가 떨어진다.&lt;/li&gt;
          &lt;li&gt;Ex) 쇼핑 사이트에서의 주문 취소&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;update-명령문-sql의-dml&quot;&gt;UPDATE 명령문 (SQL의 DML)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;DB의 테이블에서 데이터를 갱신
    &lt;ul&gt;
      &lt;li&gt;웹 페이지에서 ‘등록’이나 ‘갱신’와 같은 버튼을 클릭했을 때 처리되는 데이터 갱신 기능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DELETE 명령어와 달리 셀 단위로 데이터를 갱신할 수 있다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WHERE 구&lt;/code&gt;를 생략한 경우에는 테이블의 모든 행이 갱신된다.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;테이블에 존재하지 않는 열을 지정하면 에러가 발행하여 해당 명령은 실행되지 않는다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;기본 사용 예시&lt;/strong&gt;
    &lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&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;err&quot;&gt;열&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;값&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;WHERE&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&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-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'HEEE'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'HEEE'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'2019-04-26'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NULL&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;k&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;로&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;초기화&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SET 구의 실행순서&lt;/strong&gt;
    &lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&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;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;no&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;번&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;o&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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;번&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;MySQL에서는 기술한 식의 순서에 따라 갱신 처리가 일어난다.
        &lt;ul&gt;
          &lt;li&gt;1번에서의 no 열의 값은 갱신된 이후의 값을 반환하고 a 열은 갱신된 값을 참조한다.&lt;/li&gt;
          &lt;li&gt;Ex) 1번의 경우, 초기 no: 2, 3 -&amp;gt; 갱신 후 no: 3, 4 / a: 3, 4&lt;/li&gt;
          &lt;li&gt;2번에서의 a 열은 갱신되기 전의 값을 참조하고 이후에 no 열이 갱신된다.&lt;/li&gt;
          &lt;li&gt;Ex) 2번의 경우, 초기 no: 2, 3 -&amp;gt; 갱신 후 no: 3, 4 / a: 2, 3&lt;/li&gt;
          &lt;li&gt;즉, MySQL 의 경우 갱신식 안에서 열을 참조할 때는 처리 순서를 고려할 필요가 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Oracle에서는 SET 구에 기술한 식의 순서가 처리에 영향을 주지 않는다.
        &lt;ul&gt;
          &lt;li&gt;1, 2번 모두 no 열의 값이 항상 갱신 이전의 값을 반환하기 때문에 no 열을 참조하는 a 열의 값은 갱신 전의 값이 된다.&lt;/li&gt;
          &lt;li&gt;이후에 no 열이 갱신된다.&lt;/li&gt;
          &lt;li&gt;Ex) 1, 2번 모두, 초기 no: 2, 3 -&amp;gt; 갱신 후 no: 3, 4 / a: 2, 3&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;SQL문 기본 문법 중 select 쿼리문에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/25/db-sql-select.html&quot;&gt;SQL문 기본 문법 - 검색편(select)&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;amp;ejkGb=KOR&amp;amp;barcode=9788968482311&quot;&gt;http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;amp;ejkGb=KOR&amp;amp;barcode=9788968482311&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Mon, 13 May 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/05/13/db-sql-insert-update-delete.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/05/13/db-sql-insert-update-delete.html</guid>
        
        <category>database</category>
        
        <category>sql</category>
        
        <category>query</category>
        
        <category>db</category>
        
        
      </item>
    
      <item>
        <title>[DB] SQL문 기본 문법 - 검색편(select)</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;SQL이란
      &lt;ul&gt;
        &lt;li&gt;SQL 명령의 종류&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;SELECT 명령문 (SQL 기본 문법)
      &lt;ul&gt;
        &lt;li&gt;검색 조건 지정&lt;/li&gt;
        &lt;li&gt;검색 조건 조합&lt;/li&gt;
        &lt;li&gt;패턴 매칭에 의한 검색&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;sql문&quot;&gt;SQL문&lt;/h2&gt;
&lt;p&gt;SQL은 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;“관계형 데이터베이스” 관리 시스템(RDBMS, Relational Database Management System)을 조작&lt;/span&gt;할 때 사용하는 언어이다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;RDBMS: 행과 열을 가지는 &lt;strong&gt;표 형식&lt;/strong&gt; 데이터(2차원 데이터)를 저장하는 형태의 DB
    &lt;ul&gt;
      &lt;li&gt;행(레코드), 열(컬럼/필드), 셀(행과 열이 만나는 부분, 하나의 데이터 값)&lt;/li&gt;
      &lt;li&gt;수치형, 문자열형, 날짜시간형, NULL(값이 없는 데이터) 등의 자료형이 존재&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sql-명령의-종류&quot;&gt;SQL 명령의 종류&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;DML (Data Manipulation Language)
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;데이터 조작&lt;/strong&gt;, SQL의 가장 기본이 되는 명령셋(set)&lt;/li&gt;
      &lt;li&gt;DB에 새롭게 데이터를 추가하거나 삭제하거나 내용을 갱신하는 등에 사용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DDL (Data Definition Language)
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;데이터 정의&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;DB 객체(object)라는 데이터 그릇을 이용하여 데이터를 관리하는데, 이 같은 객체를 만들거나 삭제하는 명령어&lt;/li&gt;
      &lt;li&gt;DB 객체에는 테이블, 뷰(View) 등이 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DCL (Data Control Language)
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;데이터 제어&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;트랜잭션을 제어하는 명령과 데이터 접근 권한을 제어하는 명령 포함&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;desc-명령-sql-명령-아님&quot;&gt;DESC 명령 (SQL 명령 아님)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;테이블의 구조 참조
    &lt;ul&gt;
      &lt;li&gt;테이블에 어떤 열이 정의되어 있는지 알 수 있다.&lt;/li&gt;
      &lt;li&gt;열 이름(Field), 열의 자료형(Type), NULL 제약사항(Null), Key 지정 정보(Key), 생략된 경우의 기본값(Default) 등 해당 테이블의 구조 정보를 확인할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tablename&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;h2 id=&quot;select-명령문-sql의-dml&quot;&gt;SELECT 명령문 (SQL의 DML)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;DML에 속하는 명령으로 “질의”나 “쿼리”라 불리기도 한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;에&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;해당하는&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블의&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;모든&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;읽는다&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tablename&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;err&quot;&gt;위와&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;동일&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;대소문자&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;구별&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&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;ul&gt;
  &lt;li&gt;예약어와 DB 객체명은 대소문자를 구별하지 않는다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;검색-조건-지정&quot;&gt;검색 조건 지정&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;열 지정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;err&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;err&quot;&gt;열&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&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;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&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;ul&gt;
  &lt;li&gt;&lt;strong&gt;행 지정&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;구&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;구&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;구&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;순서&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;중요&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;수치형&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;id&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;값이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;와&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;동일한&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행만&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;id&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;값이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;가&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아닌&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행만&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;문자열형&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'아무개'&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;k&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;값&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birthday&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NULL&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;ul&gt;
  &lt;li&gt;where 구(조건식)는 ‘열과 연산자, 상수로 구성되는 식’이다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;검색-조건-조합&quot;&gt;검색 조건 조합&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;AND, OR, NOT&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AND&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&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;a&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;모두&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아닌&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&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;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&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;a&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아니거나&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아닌&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조건식&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&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;a&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아니거나&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;열이&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;아닌&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;제외한&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;나머지&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;AND는 OR에 비해 우선 순위가 높다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;패턴-매칭에-의한-검색&quot;&gt;패턴 매칭에 의한 검색&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;특정 문자나 문자열이 포함되어 있는지를 검색하고 싶은 경우 &lt;strong&gt;‘패턴 매칭’&lt;/strong&gt;(부분 검색)을 사용&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;LIKE&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-sql 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;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIKE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'패턴'&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열에&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'SQL'&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;포함하는&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIKE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'SQL%'&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;전방일치&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIKE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'%SQL%'&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;중간일치&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;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열에&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'%'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;메타문자&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;포함하는&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;행을&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;검색&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;LIKE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'%&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\%&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;%'&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;err&quot;&gt;이스케이프&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;문자&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;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;사용&lt;/span&gt; 

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;열에&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'It'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'을 포함하는 행을 검색
&amp;gt; SELECT * FROM sample WHERE text LIKE '&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;It&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'; // '&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;를&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;문자열&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;상수&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;안에&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;포함할&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;경우&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;개를&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;연속해서&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;기술&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;사용할 수 있는 메타문자(또는 와일드카드)는 &lt;strong&gt;’%’와 ‘_‘&lt;/strong&gt;가 있다.&lt;/li&gt;
  &lt;li&gt;%(퍼센트): 임의의 문자열과 매치, 빈 물자열에도 매치한다.&lt;/li&gt;
  &lt;li&gt;_(언더스코어): 임의의 문자 하나&lt;/li&gt;
  &lt;li&gt;*는 사용할 수 없다.&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- # 관련된 Post --&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;amp;ejkGb=KOR&amp;amp;barcode=9788968482311&quot;&gt;http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&amp;amp;ejkGb=KOR&amp;amp;barcode=9788968482311&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/25/db-sql-select.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/25/db-sql-select.html</guid>
        
        <category>database</category>
        
        <category>sql</category>
        
        <category>query</category>
        
        <category>db</category>
        
        
      </item>
    
      <item>
        <title>[JavaScript] 호이스팅(Hoisting)이란</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16695/&quot;&gt;Edwith 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;호이스팅(Hoisting)이란 무엇인지 이해한다.&lt;/li&gt;
    &lt;li&gt;함수선언문과 함수표현식에서의 호이스팅 차이를 이해한다.
      &lt;ul&gt;
        &lt;li&gt;let/const와 var 변수 선언에서의 호이스팅 예시&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅에 대해 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;호이스팅hoisting의-개념&quot;&gt;호이스팅(Hoisting)의 개념&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것&lt;/span&gt;을 말한다.&lt;/p&gt;

&lt;h3 id=&quot;호이스팅이란&quot;&gt;호이스팅이란&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 &lt;strong&gt;유효 범위의 최상단&lt;/strong&gt;에 선언한다.
    &lt;ul&gt;
      &lt;li&gt;자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.&lt;/li&gt;
      &lt;li&gt;함수 안에 존재하는 변수/함수선언에 대한 정보를 기억하고 있다가 실행시킨다.&lt;/li&gt;
      &lt;li&gt;유효 범위: 함수 블록 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; 안에서 유효&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
    &lt;ul&gt;
      &lt;li&gt;실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.&lt;/li&gt;
      &lt;li&gt;실제 메모리에서는 변화가 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;호이스팅의-대상&quot;&gt;호이스팅의 대상&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;var 변수 선언&lt;/strong&gt;과 &lt;strong&gt;함수선언문&lt;/strong&gt;에서만 호이스팅이 일어난다.
    &lt;ul&gt;
      &lt;li&gt;var 변수/함수의 &lt;strong&gt;선언&lt;/strong&gt;만 위로 끌어 올려지며, &lt;strong&gt;할당&lt;/strong&gt;은 끌어 올려지지 않는다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;let/const 변수 선언과 함수표현식&lt;/em&gt;에서는 호이스팅이 발생하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;간단한 예시 (var 변수 vs let/const 변수)
    &lt;div class=&quot;language-js 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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// var 변수 &lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// let 변수 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] &quot;선언&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;할당&quot;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] 발생 X&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;간단한 예시 (함수선언문 vs 함수표현식)
    &lt;div class=&quot;language-js 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;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;foo2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&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-js 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;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] 함수표현식의 변수값 &quot;선언&quot;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo&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;c1&quot;&gt;// [Hoisting] 함수선언문&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;foo2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!! &lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello2&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&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;/li&gt;
  &lt;li&gt;호이스팅은 함수선언문과 함수표현식에서 서로 다르게 동작하기 때문에 주의해야 한다.
    &lt;ul&gt;
      &lt;li&gt;변수에 할당된 함수표현식은 끌어 올려지지 않기 때문에 이때는 변수의 스코프 규칙을 그대로 따른다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;함수선언문과-함수표현식에서의-호이스팅&quot;&gt;함수선언문과 함수표현식에서의 호이스팅&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;들어가기 전: &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html&quot;&gt;함수선언문과 함수표현식의 차이&lt;/a&gt;는 다음 POST를 참고하자.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;함수선언문에서의-호이스팅&quot;&gt;함수선언문에서의 호이스팅&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;함수선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;cm&quot;&gt;/* 정상 출력 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문 &lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;선언 및 할당&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;function&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;name is inner value&quot;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&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;c1&quot;&gt;// 함수선언문 &lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;printName&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;div class=&quot;language-js 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;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 정상 출력 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] var 변수 &quot;선언&quot;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&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;c1&quot;&gt;// [Hoisting] 함수선언문&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;할당&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;function&quot;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;name is inner value&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;printName&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;ul&gt;
  &lt;li&gt;즉, 해당 예제에서는 함수선언문이 아래에 있어도 printName 함수 내에서 inner를 function으로 인식하기 때문에 오류가 발생하지 않는다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;함수표현식에서의-호이스팅&quot;&gt;함수표현식에서의 호이스팅&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;함수표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
    &lt;ul&gt;
      &lt;li&gt;함수표현식에서는 선언과 할당의 분리가 발생한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;함수표현식의 선언이 호출보다 위에 있는 경우 - 정상 출력
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 정상 */&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 함수 &quot;호출&quot;&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&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;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;name is inner value&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 정상 */&lt;/span&gt;
 &lt;span class=&quot;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] 함수표현식의 변수값 &quot;선언&quot;&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] var 변수값 &quot;선언&quot;&lt;/span&gt;

     &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &quot;할당&quot;&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 함수 &quot;호출&quot;&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&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;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;name is inner value&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;함수표현식의 선언이 호출보다 아래에 있는 경우 (&lt;em&gt;var 변수&lt;/em&gt;에 할당) - &lt;strong&gt;&lt;em&gt;TypeError&lt;/em&gt;&lt;/strong&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 오류 */&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;undefined&quot;: 선언은 되어 있지만 값이 할당되어있지 않은 경우&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!!&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

     &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; TypeError: inner is not a function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */&lt;/span&gt;
 &lt;span class=&quot;cm&quot;&gt;/* 오류 */&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [Hoisting] 함수표현식의 변수값 &quot;선언&quot;&lt;/span&gt;

     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;undefined&quot;&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!!&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

     &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; TypeError: inner is not a function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; printName에서 “inner is not defined” 이라고 오류가 나오지 않고, “inner is not a function”이라는 TypeError가 나오는 이유?&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; printName이 실행되는 순간 (Hoisting에 의해) inner는 ‘undefined’으로 지정되기 때문&lt;/li&gt;
      &lt;li&gt;inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;함수표현식의 선언이 호출보다 아래에 있는 경우 (&lt;em&gt;const/let 변수&lt;/em&gt;에 할당) - &lt;strong&gt;&lt;em&gt;ReferenceError&lt;/em&gt;&lt;/strong&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 오류 */&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!!&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  
     &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

     &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; ReferenceError: inner is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;let/const의 경우, 호이스팅이 일어나지 않기 때문에 위의 예시 그대로 이해하면 된다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.log(inner);&lt;/code&gt;에서 inner에 대한 선언이 되어있지 않기 때문에 이때는 “inner is not defined” 오류가 발생한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;함수표현식보다 함수선언문을 더 자주 사용하지만, 어떤 코딩컨벤션에서는 함수표현식을 권장하기도 한다.
    &lt;ul&gt;
      &lt;li&gt;즉, 어떤 컨벤션을 갖던지 한가지만 정해서 사용하는 게 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;호이스팅-우선순위&quot;&gt;호이스팅 우선순위&lt;/h2&gt;
&lt;h3 id=&quot;같은-이름의-var-변수-선언과-함수-선언에서의-호이스팅&quot;&gt;같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;변수 선언이 함수 선언보다 위로 끌어올려진다.
    &lt;div class=&quot;language-js 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;yuddomack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;everyone&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bye&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&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-js 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;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 1. [Hoisting] 변수값 선언 &lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 

  &lt;span class=&quot;c1&quot;&gt;// 2. [Hoisting] 함수선언문&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;yuddomack&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;everyone&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;c1&quot;&gt;// 3. 변수값 할당&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bye&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;string&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;string&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;값이 할당되어 있지 않은 변수와 값이 할당되어 있는 변수에서의 호이스팅
    &lt;div class=&quot;language-js 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Heee&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 값 할당 X&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&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;c1&quot;&gt;// 같은 이름의 함수 선언&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;myName Function&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&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;c1&quot;&gt;// 같은 이름의 함수 선언&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;yourName Function&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;string&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;yourName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;gt; &quot;function&quot;&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;li&gt;값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어쓴다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;TIP&lt;/mark&gt; 호이스팅 사용 시 주의&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록 한다.
    &lt;ul&gt;
      &lt;li&gt;호이스팅을 제대로 모르더라도 함수와 변수를 가급적 코드 상단부에서 선언하면, 호이스팅으로 인한 스코프 꼬임 현상은 방지할 수 있다.&lt;/li&gt;
      &lt;li&gt;let/const를 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까?
    &lt;ul&gt;
      &lt;li&gt;ES6를 어디에서든 쓸 수 있으려면 아직 시간이 더 필요하므로 ES5로 트랜스컴파일을 해야한다.&lt;/li&gt;
      &lt;li&gt;따라서 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JavaScript의 변수, 연산자, 타입에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/18/javascript-variable-and-type.html&quot;&gt;자바스크립트의 변수, 연산자, 타입의 종류&lt;/a&gt;를 참고하시기 바랍니다&lt;/li&gt;
  &lt;li&gt;JavaScript의 비교, 반복, 문자열에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/19/javascript-if-switch-for.html&quot;&gt;자바스크립트의 비교, 반복, 문자열 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JavaScript의 함수선언문과 함수표현식의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html&quot;&gt;함수표현식 vs 함수선언문&lt;/a&gt;를 참고하시기 바랍니다&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16695/&quot;&gt;https://www.edwith.org/boostcourse-web/lecture/16695/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting#recentComments&quot;&gt;https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting#recentComments&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Mon, 22 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html</guid>
        
        <category>javascript</category>
        
        <category>function</category>
        
        <category>hoisting</category>
        
        
      </item>
    
      <item>
        <title>[JavaScript] 함수선언문과 함수표현식의 차이</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16695/&quot;&gt;Edwith 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;자바스크립트의 함수의 개념과 특징에 대해 이해한다.&lt;/li&gt;
    &lt;li&gt;함수선언문과 함수표현식의 차이를 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;함수&quot;&gt;함수&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;함수는 여러 개의 인자를 받아서, 그 결과를 출력한다.&lt;/li&gt;
  &lt;li&gt;파라미터의 개수와 인자의 개수가 일치하지 않아도 오류가 발생하지 않는다.
    &lt;ul&gt;
      &lt;li&gt;만약, 파라미터 1개가 정의된 함수를 부를 때, 인자의 개수를 0개만 넣어 실행하면 이미 정의된 파라미터(매개변수)는 undefined이라는 값을 갖게 된다.&lt;/li&gt;
      &lt;li&gt;이는 변수는 초기화됐지만, 값이 할당되지 않았기 때문이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자바스크립트에서는 &lt;strong&gt;함수도 객체&lt;/strong&gt;이다.
    &lt;ul&gt;
      &lt;li&gt;따라서 다른 객체와 마찬가지로 넘기거나 할당할 수 있다.&lt;/li&gt;
      &lt;li&gt;함수를 &lt;em&gt;객체 프로퍼티&lt;/em&gt;에 할당할 수도 있다.
        &lt;div class=&quot;language-js 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;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&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;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;testFunc&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// test!!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;함수를 &lt;em&gt;객체 배열 요소&lt;/em&gt;로 할당할 수도 있다.
        &lt;div class=&quot;language-js 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;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arr&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;arr&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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;testFunc&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;arr&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;// test!!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;함수-호출-vs-함수-참조&quot;&gt;함수 호출 vs 함수 참조&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;함수 호출&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;함수 식별자 뒤에 괄호를 쓰면 함수 본문(Body)을 실행한다&lt;/li&gt;
      &lt;li&gt;함수를 호출한 표현식은 반환값이 된다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testFunc()&lt;/code&gt; // test!! (함수 호출)
        &lt;div class=&quot;language-js 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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;firstname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;함수 참조&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;함수 식별자 뒤에 괄호를 쓰지 않으면 함수는 실행되지 않는다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;testFunc&lt;/code&gt; // function testFunc() // (함수 참조)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const f = testFunc&lt;/code&gt;와 같이 함수를 변수에 할당하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f()&lt;/code&gt;과 같이 다른 이름으로 함수를 호출할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;원시값-매개변수-vs-객체-매개변수&quot;&gt;원시값 매개변수 vs 객체 매개변수&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;함수를 호출하면 함수 매개변수는 변수 자체가 아니라 그 값을 전달받는다.
    &lt;ul&gt;
      &lt;li&gt;따라서 넘겨받은 &lt;strong&gt;원시값&lt;/strong&gt; 매개변수를 함수 내에서 변경하더라도 밖에서는 변경되지 않는다.&lt;/li&gt;
      &lt;li&gt;하지만 넘겨받은 매개변수가 &lt;strong&gt;객체&lt;/strong&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;li&gt;반면 객체는 바뀔 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;반환값과-undefined&quot;&gt;반환값과 undefined&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;함수는 어떤 타입의 값이라도 반환할 수 있다.&lt;/li&gt;
  &lt;li&gt;자바스크립트 함수는 반드시 return값이 존재하며, 없을 때는 기본 반환값인 &lt;strong&gt;‘undefined’&lt;/strong&gt;가 반환된다.
    &lt;ul&gt;
      &lt;li&gt;자바스크립트에서는 void 타입이 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ex. 반환값: undefined
    &lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;firstname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;arguments-객체&quot;&gt;arguments 객체&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;함수 호출 시에 넘겨진 실제 인자값을 가지는 객체&lt;/li&gt;
  &lt;li&gt;함수가 실행되면 그 안에는 arguments라는 &lt;strong&gt;특별한 지역변수&lt;/strong&gt;가 자동으로 생성된다.
    &lt;ul&gt;
      &lt;li&gt;arguments의 타입은 객체이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자바스크립트 함수는 선언한 파라미터보다 더 많은 인자를 보낼 수도 있다.
    &lt;ul&gt;
      &lt;li&gt;이때 넘어온 인자를 arguments로 하나씩 접근할 수 있다.&lt;/li&gt;
      &lt;li&gt;arguments는 배열의 형태(array-like)를 가지고 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;arguments는 배열 타입(array)은 아니다.
    &lt;ul&gt;
      &lt;li&gt;따라서 배열의 메서드를 사용할 수 없다.
        &lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arguments&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;nx&quot;&gt;a&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;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// { '0':1, '1':2, '2':3 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;자바스크립트의 가변인자를 받아서 처리하는 함수를 만드는 상황에서 arguments 속성을 유용하게 사용할 수 있다.(메서드에 넘겨 받을 인자의 개수를 모를 때)
    &lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&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;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&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;c1&quot;&gt;// 인자의 개수가 중요한 경우 &lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;errer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;otherMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arguments&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;// 다른 메서드에 가변인자를 넘겨주는 경우 &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;/li&gt;
  &lt;li&gt;arguments 사용 시 주의
    &lt;ul&gt;
      &lt;li&gt;arguments도 남용하면 변경에 약한 코드가 된다.&lt;/li&gt;
      &lt;li&gt;arguments를 함부로 수정해서도 안된다. 수정이 된다 하더라도 수정을 해서 해당 값을 바꾸려고 하는 것을 좋지 않다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;함수선언문과-함수표현식의-차이&quot;&gt;함수선언문과 함수표현식의 차이&lt;/h2&gt;
&lt;h3 id=&quot;함수선언문-function-declaration&quot;&gt;함수선언문 (Function Declaration)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;일반적인 프로그래밍 언어에서의 함수 선언과 비슷한 형식
    &lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;함수명&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;err&quot;&gt;구현&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;로직&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-js 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;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEEE&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;nx&quot;&gt;myname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;  &lt;span class=&quot;nx&quot;&gt;firstname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;함수표현식-function-expression&quot;&gt;함수표현식 (Function Expression)&lt;/h3&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;함수표현식은 익명 함수표현식과 기명 함수표현식으로 나눌 수 있다.
    &lt;ul&gt;
      &lt;li&gt;일반적으로 함수표현식이라고 부르면 앞에 익명이 생략된 형태라고 볼 수 있다.&lt;/li&gt;
      &lt;li&gt;익명 함수표현식: 함수에 식별자가 주어지지 않는다.&lt;/li&gt;
      &lt;li&gt;기명 함수표현식: 함수의 식별자가 존재한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;함수표현식의 장점
    &lt;ul&gt;
      &lt;li&gt;클로져로 사용&lt;/li&gt;
      &lt;li&gt;콜백으로 사용(다른 함수의 인자로 넘길 수 있음)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// (익명) 함수표현식&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;익명 함수표현식&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test2&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;c1&quot;&gt;// 기명 함수표현식 &lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;기명 함수표현식&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;함수선언문과-함수표현식의-차이-1&quot;&gt;함수선언문과 함수표현식의 차이&lt;/h3&gt;
&lt;ul&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;함수표현식 Error 예시
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 정상 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&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;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;name is inner value&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 오류 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;undefined&quot;: 선언은 되어 있지만 값이 할당되어있지 않은 경우&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!!&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// TypeError: inner is not a function&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 오류 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;firstname&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;c1&quot;&gt;// 함수선언문&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Hoisting - 변수값을 끌어올린다. (선언은 되어 있지만 값이 할당되어있지 않은 경우)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;undefined&quot;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ERROR!!&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;name is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;c1&quot;&gt;// 함수표현식 &lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner value&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;printName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// TypeError: inner is not a function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Q.&lt;/strong&gt; “printName이 is not defined” 이라고 오류가 나오지 않고, function이 아니라는 TypeError가 나오는 이유?&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;A.&lt;/strong&gt; printName이 실행되는 순간 (&lt;a href=&quot;&quot;&gt;Hoisting&lt;/a&gt;에 의해) inner는 ‘undefined’으로 지정되기 때문&lt;/li&gt;
      &lt;li&gt;inner가 undefined라는 것은 즉, 아직은 함수로 인식이 되지 않고 있다는 것을 의미한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;함수표현식보다 함수선언문을 더 자주 사용하지만, 어떤 코딩컨벤션에서는 함수표현식을 권장하기도 한다.
    &lt;ul&gt;
      &lt;li&gt;즉, 어떤 컨벤션을 갖던지 한가지만 정해서 사용하는 게 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JavaScript의 변수, 연산자, 타입에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/18/javascript-variable-and-type.html&quot;&gt;자바스크립트의 변수, 연산자, 타입의 종류&lt;/a&gt;를 참고하시기 바랍니다&lt;/li&gt;
  &lt;li&gt;JavaScript의 비교, 반복, 문자열에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/19/javascript-if-switch-for.html&quot;&gt;자바스크립트의 비교, 반복, 문자열 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JavaScript의 호이스팅에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html&quot;&gt;자바스크립트의 호이스팅이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16695/&quot;&gt;https://www.edwith.org/boostcourse-web/lecture/16695/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/&quot;&gt;https://joshua1988.github.io/web-development/javascript/function-expressions-vs-declarations/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/vue-pwa-vue-js-%EC%A4%91%EA%B8%89/&quot;&gt;장기효 (캡틴판교) - Vue.js 중급 강좌, 웹앱 제작으로 배워보는 Vue.js, ES6, Vuex&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sat, 20 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html</guid>
        
        <category>javascript</category>
        
        <category>function</category>
        
        
      </item>
    
      <item>
        <title>[JavaScript] 자바스크립트의 비교문/분기문/반복문, 문자열</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16694/&quot;&gt;Edwith 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;자바스크립트의 비교문/분기문/반복문에 대해 이해한다&lt;/li&gt;
    &lt;li&gt;자바스크립트의 문자열 처리에 대해 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;비교문&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#%EC%A1%B0%EA%B1%B4%EB%AC%B8&quot;&gt;비교문&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;if, else if, else 문을 통해서 다양한 비교문을 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&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;nx&quot;&gt;a&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;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;not ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ok &lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&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;nx&quot;&gt;a&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;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;not ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// not ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;분기문&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#switch%EB%AC%B8&quot;&gt;분기문&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;로직을 분기하기 위해서 if 문 이외에도 switch 문을 통해서도 해결할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;반복문&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Loops_and_iteration#for_%EB%AC%B8&quot;&gt;반복문&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;for 문이나 while문을 사용해서 반복문을 구현할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;howMany&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectObject&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;numberSelected&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;selectObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 비효율적 (배열의 길이를 계속 계산)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selectObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selected&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;nx&quot;&gt;numberSelected&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;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;nx&quot;&gt;numberSelected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&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;ul&gt;
  &lt;li&gt;배열의 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forEach&lt;/code&gt;와 같은 메서드도 있고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for-of&lt;/code&gt;를 통한 탐색도 자주 사용된다.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for-in&lt;/code&gt;은 객체를 탐색할 때 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;for 문의 성능 개선
    &lt;ol&gt;
      &lt;li&gt;배열의 길이 한 번만 계산
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for (var i = 0; len = selectObject.options.length; i &amp;lt; len; i++)&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Reverse Iteration
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for (var len = selectObject.options.length; i = len; i &amp;gt; len; i--)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;시작 포인트를 배열의 길이로 하고, 포인트 값을 감소하면서 반복문을 도는 형태&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;mark&gt;TIP&lt;/mark&gt; 반대로 반복문을 동작시키는(reverse iteration) 경우가 실제 브라우저에서 얼마나 성능차이가 있을까?
    &lt;ul&gt;
      &lt;li&gt;현대의 자바스크립트 엔진은 최적화를 통해 반복문을 최대한 빠르게 처리하는 과정을 거쳐왔기 때문에 실제로 실험을 해보면 그 차이가 미미하다.&lt;/li&gt;
      &lt;li&gt;따라서 for문을 무조건 반대로 구현할 필요는 없다.&lt;/li&gt;
      &lt;li&gt;이런 상황이외에도 자바스크립트의 구현 방법에 따라 (for 가 빠를까 while 빠를까? 등) 성능차이는 그리 크지 않다.&lt;/li&gt;
      &lt;li&gt;따라서 일반적으로는 &lt;strong&gt;코드의 가독성&lt;/strong&gt;에 좀 더 우선 집중하는 게 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;문자열-처리&quot;&gt;문자열 처리&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;자바스크립트의 문자와 문자열은 같은 타입으로 모두 문자열이다.
    &lt;div class=&quot;language-js 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;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;abc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// string&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// string&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// string. single quote도 사용가능.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;문자열에 다양한 메서드가 있다.
    &lt;div class=&quot;language-js 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;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ab:cd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [&quot;ab&quot;,&quot;cd&quot;]&lt;/span&gt;
 &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ab:cd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;ab$cd&quot;&lt;/span&gt;
 &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; abcde  &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// &quot;abcde&quot;&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;/li&gt;
  &lt;li&gt;정규표현식으로도 문자열을 처리할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JavaScript의 변수, 연산자, 타입에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/18/javascript-variable-and-type.html&quot;&gt;자바스크립트의 변수, 연산자, 타입의 종류&lt;/a&gt;를 참고하시기 바랍니다&lt;/li&gt;
  &lt;li&gt;JavaScript의 함수선언문과 함수표현식의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html&quot;&gt;함수표현식 vs 함수선언문&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JavaScript의 호이스팅에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html&quot;&gt;자바스크립트의 호이스팅이란&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16694/&quot;&gt;https://www.edwith.org/boostcourse-web/lecture/16693/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#%EC%A1%B0%EA%B1%B4%EB%AC%B8&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#조건문&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#switch%EB%AC%B8&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#switch문&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Loops_and_iteration#for_%EB%AC%B8&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Loops_and_iteration#for_문&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 19 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/19/javascript-if-switch-for.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/19/javascript-if-switch-for.html</guid>
        
        <category>javascript</category>
        
        
      </item>
    
      <item>
        <title>[JavaScript] 자바스크립트의 변수, 연산자, 타입의 종류</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16693/&quot;&gt;Edwith 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;자바스크립트의 변수의 종류를 확인한다.
      &lt;ul&gt;
        &lt;li&gt;var과 let, const의 차이에 대해 이해한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;자바스크립트의 연산자의 종류 및 개념을 이해한다.&lt;/li&gt;
    &lt;li&gt;자바스크립트의 타입의 종류를 확인한다.
      &lt;ul&gt;
        &lt;li&gt;자바스크립트에서 type 체크 방법에 대해 이해한다.&lt;/li&gt;
        &lt;li&gt;자바스크립트에서 null 체크 방법에 대해 이해한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;자바스크립트의-버전&quot;&gt;자바스크립트의 버전&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;자바스크립트 버전은 ECMAScript(줄여서 ES, 이크마스크립트)의 버전에 따라서 결정되고, 이를 자바스크립트 실행 엔진이 반영한다.
    &lt;ul&gt;
      &lt;li&gt;자바스크립트 엔진은 작성한 JS 코드를 한 줄씩 해석하면서 실행을 준비한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;ES5, ES6(ES2015).. 이런 식으로 버전을 일컫는다.&lt;/li&gt;
  &lt;li&gt;2018년을 중심으로 ES6를 지원하는 브라우저가 많아서 몇 년간 ES6 문법이 표준으로 쓰이고 있다.&lt;/li&gt;
  &lt;li&gt;ES6는 ES5문법을 포함하고 있어 하위호환성 문제가 없다.
    &lt;ul&gt;
      &lt;li&gt;다만 feature별로 지원하지 않는 브라우저가 있을 수 있어 주의해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://babeljs.io/&quot;&gt;Bable&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;구 버전 브라우저 중에서는 ES6의 기능을 지원하지 않는 브라우저가 있으므로 &lt;strong&gt;transpiling&lt;/strong&gt;이 필요&lt;/li&gt;
      &lt;li&gt;ES6의 문법을 각 브라우저의 호환 가능한 ES5로 변환하는 컴파일러&lt;/li&gt;
      &lt;li&gt;Babel 온라인 에디터: &lt;a href=&quot;https://babeljs.io/repl/&quot;&gt;https://babeljs.io/repl/&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;변수&quot;&gt;변수&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;변수는 var, let, const로 선언할 수 있다.&lt;/li&gt;
  &lt;li&gt;어떤 것을 사용하는가에 의해서 scope, 즉 변수의 유효범위가 달라진다.&lt;/li&gt;
  &lt;li&gt;ES6 이전 버전에서는 var를 사용해서 변수를 선언할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;var로 선언한 변수는 끌어올린다는 뜻의 &lt;strong&gt;호이스팅(hoisting)&lt;/strong&gt; 이라는 매커니즘을 따른다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;aaa&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;aaa&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&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;변수의-scope&quot;&gt;변수의 Scope&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;에 상관없이 스코프가 설정된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-javascript 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&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;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 15&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;es6-새로운-변수-선언-방식---const-let&quot;&gt;ES6 새로운 변수 선언 방식 - const, let&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;블록 단위 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;로 변수의 범위가 제한되었다.
    &lt;div class=&quot;language-js 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;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&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;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&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;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 10&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Uncaught ReferenceError: i is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const&lt;/code&gt;: 한번 선언한 값에 대해서 변경할 수 없다.(상수 개념)
    &lt;div class=&quot;language-js 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;cm&quot;&gt;/* 예시 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Uncaught TypeError: Assignment to constant variable&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* [주의!] 하지만, 객체나 배열의 내부는 변경할 수 있다. */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&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;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// {num: 10}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&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;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [20]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt;: 한번 선언한 값에 대해서 다시 선언할 수 없다. 변경은 가능
    &lt;ul&gt;
      &lt;li&gt;메모리에 할당하면 다시 할당하지 못함&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;간단한 scope 예시
    &lt;div class=&quot;language-js 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;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&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;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&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;c1&quot;&gt;// 새로운 블록 안에 새로운 x의 스코프가 생김&lt;/span&gt;
          &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sneaky&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 위에 이미 const로 x를 선언했으므로 다시 값을 대입하면 Error&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// 이전 블록 범위로 돌아왔기 때문에 'let x'에 해당하는 메모리에 값을 대입&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// SyntaxError: Identifier 'x' has already been declared&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&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;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;연산자&quot;&gt;연산자&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;연산자 우선순위를 표현하기 위해서는 ()를 사용하면 된다.&lt;/li&gt;
  &lt;li&gt;수학 연산자, 논리 연산자, 관계 연산자, 삼항 연산자 등이 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;수학-연산자&quot;&gt;수학 연산자&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;+, -, *, /, %(나머지) 등이 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;논리-연산자&quot;&gt;논리 연산자&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt; 연산자
    &lt;ul&gt;
      &lt;li&gt;모든 값이 true인지 확인하지만, 첫 번째가 이미 false라면 그 이후의 값은 확인하지 않는다.&lt;/li&gt;
      &lt;li&gt;모든 값이 true인 경우 마지막 값이 할당된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt; 연산자
    &lt;ul&gt;
      &lt;li&gt;첫 번째가 true인 경우 그 이후의 값은 확인하지 않고 첫 번째 값이 할당된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;// or 연산자 활용&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;myname&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// myname &lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// test (&amp;amp;&amp;amp;의 경우, 뒤의 값이 할당된다.)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// default &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;삼항-연산자&quot;&gt;삼항 연산자&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;간단한 비교와 값 할당은 삼항연산자를 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-js 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;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&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;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&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;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;fail&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// ok &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;비교-연산자&quot;&gt;비교 연산자&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;비교는 == 보다는 &lt;strong&gt;===&lt;/strong&gt; 를 사용한다.
    &lt;ul&gt;
      &lt;li&gt;=== 의 경우는 Type까지 확인하는 연산자이다.&lt;/li&gt;
      &lt;li&gt;== 의 경우 임의적으로 Type을 바꿔서 비교하기 때문에 원하는 결과와 다른 값이 나올 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;== 로 인한 다양한 오류 상황 예시
    &lt;div class=&quot;language-js 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;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true &lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// false (null은 객체)&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// false &lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;TIP&lt;/mark&gt; 자바스크립트의 null 체크에서의 ! 사용 시 주의&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;0, null, undefined, “”, {}, []
    &lt;div class=&quot;language-js 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;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// false&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;target&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;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&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;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// false &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;자바스크립트의-타입&quot;&gt;자바스크립트의 타입&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;undefined, null, boolean, number, string, object, function, array, Date, RegExp 등&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;기본형과-참조형의-종류&quot;&gt;기본형과 참조형의 종류&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Primitive
    &lt;ul&gt;
      &lt;li&gt;Number&lt;/li&gt;
      &lt;li&gt;String&lt;/li&gt;
      &lt;li&gt;Boolean&lt;/li&gt;
      &lt;li&gt;null&lt;/li&gt;
      &lt;li&gt;undefined&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Reference: 기본형 데이터의 집합이라고 할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;Object
        &lt;ul&gt;
          &lt;li&gt;Array&lt;/li&gt;
          &lt;li&gt;Function&lt;/li&gt;
          &lt;li&gt;RegExp&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;기본형과-참조형의-차이점&quot;&gt;기본형과 참조형의 차이점&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;기본형: 값을 그대로 할당&lt;/li&gt;
  &lt;li&gt;참조형: 값이 저장된 주소값을 할당(참조)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;자바스크립트-type-체크&quot;&gt;자바스크립트 Type 체크&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;컴파일 단계가 없는 JavaScript의 Type은 선언할 때가 아니고, &lt;strong&gt;실행 타임&lt;/strong&gt; (Dynamic Type)에 결정된다.
    &lt;ul&gt;
      &lt;li&gt;함수 안에서의 파라미터나 변수는 실행될 때 그 타입이 결정된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;타입을 체크하는 또렷한 방법은 없다.
    &lt;ul&gt;
      &lt;li&gt;정확하게는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toString.call()&lt;/code&gt; 함수를 이용해서 그 결과를 매칭하곤 하는데, 문자, 숫자와 같은 자바스크립트 기본 타입은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typeof&lt;/code&gt; 키워드를 사용해서 체크할 수 있습니다.&lt;/li&gt;
      &lt;li&gt;배열은 타입을 체크하는 isArray함수가 표준으로 생겼다. (IE와 같은 구 브라우저를 사용해야 한다면 지원범위를 살펴보고 사용)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;예시
    &lt;div class=&quot;language-js 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;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;[object String]&quot;&lt;/span&gt;
  
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;string&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JavaScript의 비교, 반복, 문자열에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/19/javascript-if-switch-for.html&quot;&gt;자바스크립트의 비교, 반복, 문자열 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JavaScript의 함수선언문과 함수표현식의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/20/function-declaration-vs-function-expression.html&quot;&gt;함수표현식 vs 함수선언문&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;JavaScript의 호이스팅에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html&quot;&gt;자바스크립트의 호이스팅이란&lt;/a&gt;을 참고하시기 바랍니다.
    &lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
    &lt;blockquote&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16693/&quot;&gt;https://www.edwith.org/boostcourse-web/lecture/16693/&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 18 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/18/javascript-variable-and-type.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/18/javascript-variable-and-type.html</guid>
        
        <category>javascript</category>
        
        
      </item>
    
      <item>
        <title>[Network] HTTP의 동작 및 HTTP Message 형식</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.edwith.org/boostcourse-web/lecture/16661/&quot;&gt;Edwith 강의&lt;/a&gt; 참고&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Internet이란
      &lt;ul&gt;
        &lt;li&gt;IP 주소와 Port 번호의 개념을 이해한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;HTTP란
      &lt;ul&gt;
        &lt;li&gt;HTTP의 기본 특징 및 동작에 대해 이해한다.&lt;/li&gt;
        &lt;li&gt;HTTP와 HTTPS의 차이에 대해 이해한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;HTTP Message
      &lt;ul&gt;
        &lt;li&gt;HTTP Request 형식&lt;/li&gt;
        &lt;li&gt;HTTP Response 형식&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;URI와 URL의 차이에 대해 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;인터넷네트워크-통신의-이해&quot;&gt;인터넷(네트워크 통신)의 이해&lt;/h2&gt;
&lt;h3 id=&quot;인터넷-internet이란&quot;&gt;인터넷 (Internet)이란&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;TCP/IP 기반의 네트워크가 전세계적으로 확대되어 하나의 연결된 네트워크들의 네트워크 (&lt;strong&gt;네트워크의 결합체&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;인터넷 != WWW(World Wide Web)
    &lt;ul&gt;
      &lt;li&gt;인터넷 기반의 대표 서비스 중 하나가 www라고 할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;인터넷 기반의 서비스들&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;이름&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;프로토콜&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;포트&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;기능&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;www&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;HTTP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;80&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;웹 서비스&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Email&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;SMTP/POP3/IMAP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;25/110/114&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;이메일 서비스&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;FTP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;FTP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;21&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;파일 전송 서비스&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;DNS&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;TCP/UDP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;53&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;네임 서비스&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;NEWS&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;NNTP&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;119&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;인터넷 뉴스 서비스&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;ul&gt;
  &lt;li&gt;물리적인 하나의 컴퓨터(IP 주소)에는 여러 개의 서버가 동작할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;각각의 서버들은 Port라는 값으로 구분돼서 동작한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;mark&gt;TIP&lt;/mark&gt; IP 주소와 Port 번호의 개념
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;IP 주소&lt;/strong&gt; 또는 &lt;strong&gt;도메인 이름&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;하드웨어 서버(물리적인 컴퓨터)를 찾기 위해 반드시 필요한 정보&lt;/li&gt;
          &lt;li&gt;Ex) 집 주소&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Port 번호&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;해당 물리적인 컴퓨터 안에 존재하는 소프트웨어 서버를 찾기 위한 정보&lt;/li&gt;
          &lt;li&gt;하나의 물리적인 컴퓨터에는 여러 개의 소프트웨어 프로그램이 각각의 Socket을 사용하여 데이터 통신을 하고 있기 때문에 각각의 Socket을 구분할 필요가 있다. Port 번호를 통해 각 Socket을 구분할 수 있다.&lt;/li&gt;
          &lt;li&gt;0보다 큰 숫자로 구성되어 있다.&lt;/li&gt;
          &lt;li&gt;Ex) 집 안의 여러 방 번호&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;웹의-동작-http-프로토콜의-이해&quot;&gt;웹의 동작 (HTTP 프로토콜의 이해)&lt;/h2&gt;
&lt;h3 id=&quot;http-hypertext-transfer-protocol란&quot;&gt;HTTP (Hypertext Transfer Protocol)란&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;웹 브라우저와 웹 서버 간의 서로 통신하기 위한 규약&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;즉, HTTP(Hypertext Transfer Protocol)란 서버와 클라이언트가 인터넷상에서 데이터를 주고받기 위한 프로토콜(protocol)을 말한다.&lt;/li&gt;
      &lt;li&gt;HTTP는 계속 발전하여 HTTP/2까지 버전이 등장한 상태&lt;/li&gt;
      &lt;li&gt;팀 버너스리(Tim Berners-Lee)와 그가 속한 팀은 CERN에서 HTML뿐만 아니라 웹 브라우저 및 웹 브라우저 관련 기술과 HTTP를 발명하였다.&lt;/li&gt;
      &lt;li&gt;어떤 종류의 데이터도 전송할 수 있도록 설계되어있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;mark&gt;TIP&lt;/mark&gt; HTTP와 HTTPS의 차이
    &lt;ul&gt;
      &lt;li&gt;HTTP 프로토콜
        &lt;ul&gt;
          &lt;li&gt;웹상에서 클라이언트와 서버 간에 요청/응답으로 정보를 주고 받을 수 있는 프로토콜&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;HTTPS 프로토콜
        &lt;ul&gt;
          &lt;li&gt;웹 통신 프로토콜인 HTTP의 보안이 강화된 버전&lt;/li&gt;
          &lt;li&gt;HTTPS는 소켓 통신에서 일반 텍스트를 이용하는 대신에, SSL이나 TLS 프로토콜을 통해 세션 데이터를 암호화한다.&lt;/li&gt;
          &lt;li&gt;따라서 데이터의 적절한 보호를 보장한다.&lt;/li&gt;
          &lt;li&gt;HTTPS의 기본 TCP/IP포트는 443이다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;http-통신-과정&quot;&gt;HTTP 통신 과정&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP는 서버/클라이언트 모델을 따른다.
    &lt;ul&gt;
      &lt;li&gt;클라이언트 -&amp;gt; &lt;strong&gt;요청&lt;/strong&gt; -&amp;gt; 서버 -&amp;gt; &lt;strong&gt;응답&lt;/strong&gt; -&amp;gt; 클라이언트&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;특징&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;비연결 지향(Connectionless)
            &lt;ul&gt;
              &lt;li&gt;클라이언트가 request를 서버에 보내고, 서버가 클라이언트에 요청에 맞는 response를 보내면 바로 연결을 끊는다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;무상태(Stateless)
            &lt;ul&gt;
              &lt;li&gt;연결을 끊는 순간 클라이언트와 서버의 통신은 끝나며 상태 정보를 유지하지 않는다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;장점&lt;/strong&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;strong&gt;단점&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;연결을 끊어버리기 때문에, 클라이언트의 이전 상황을 알 수가 없다.&lt;/li&gt;
          &lt;li&gt;이러한 특징을 무상태(Stateless)라고 말한다.&lt;/li&gt;
          &lt;li&gt;이러한 특징 때문에 정보를 유지하기 위해서 Cookie와 같은 기술이 등장하게 되었다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;img src=&quot;/images/network/http-network-connect.png&quot; alt=&quot;&quot; /&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;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;http-메시지-형식&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Messages&quot;&gt;HTTP 메시지 형식&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/network/http-example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;http-요청-메시지-형식&quot;&gt;HTTP 요청 메시지 형식&lt;/h3&gt;
&lt;p&gt;HTTP Request Message = &lt;strong&gt;Request Header + 빈 줄 + Request Body&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Header
    &lt;ul&gt;
      &lt;li&gt;첫 번째 줄 (start-line)
        &lt;ul&gt;
          &lt;li&gt;요청 메서드 + 요청 URI + HTTP 프로토콜 버전&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /background.png HTTP/1.0&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST / HTTP 1.1&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;두 번째 줄 ~ (http headers)
        &lt;ul&gt;
          &lt;li&gt;Header 정보들 (‘Header Name: Header Value’ 형태)&lt;/li&gt;
          &lt;li&gt;각 줄은 Line Feed(LF)와 Carriage Return(CR)으로 구분된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;빈 줄 (empty-line)
    &lt;ul&gt;
      &lt;li&gt;요청에 대한 모든 메타 정보가 전송되었음을 알린다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Body
    &lt;ul&gt;
      &lt;li&gt;POST, PUT의 경우에만 존재&lt;/li&gt;
      &lt;li&gt;요청과 관련된 내용 (HTML 폼 콘텐츠 등)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ex
&lt;img src=&quot;/images/network/http-request.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;http-응답-메시지-형식&quot;&gt;HTTP 응답 메시지 형식&lt;/h3&gt;
&lt;p&gt;HTTP Response Message = &lt;strong&gt;Response Header + 빈 줄 + Response Body&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Header
    &lt;ul&gt;
      &lt;li&gt;첫 번째 줄 (status-line)
        &lt;ul&gt;
          &lt;li&gt;HTTP 프로토콜 버전 + 응답 코드 + 응답 메시지&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP/1.1 404 Not Found.&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;두 번째 줄 ~ (http headers)
        &lt;ul&gt;
          &lt;li&gt;Header 정보들 (‘Header Name: Header Value’ 형태)
            &lt;ul&gt;
              &lt;li&gt;날짜, 웹서버 이름, 웹서버 버전, 콘텐츠 타입, 콘텐츠 길이, 캐시 제어 방식 등&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;각 줄은 Line Feed(LF)와 Carriage Return(CR)으로 구분된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;빈 줄 (empty-line)
    &lt;ul&gt;
      &lt;li&gt;요청에 대한 모든 메타 정보가 전송되었음을 알린다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Body
    &lt;ul&gt;
      &lt;li&gt;실제 응답 리소스 데이터&lt;/li&gt;
      &lt;li&gt;201, 204와 같은 상태 코드를 가진 응답에는 보통 body가 존재하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ex
&lt;img src=&quot;/images/network/http-response.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;http-기본-속성-개념&quot;&gt;HTTP 기본 속성 개념&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;요청 메서드
    &lt;ul&gt;
      &lt;li&gt;서버에게 요청의 종류를 알려주기 위해 사용&lt;/li&gt;
      &lt;li&gt;최초의 웹 서버는 GET 방식만 지원&lt;/li&gt;
      &lt;li&gt;각 메서드의 사용 목적
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;GET:&lt;/strong&gt; 정보 요청 (SELECT)&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;POST:&lt;/strong&gt; 정보 밀어넣기 (INSERT)&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;PUT:&lt;/strong&gt; 정보 업데이트 (UPDATE)&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;DELETE:&lt;/strong&gt; 정보 삭제 (DELETE)&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;HEAD:&lt;/strong&gt; (HTTP) 헤더 정보만 요청하는 메서드. 해당 자원이 존재하는지 혹은 서버에 문제가 없는지를 확인&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;OPTIONS:&lt;/strong&gt; 웹 서버가 지원하는 메서드의 종류를 요청&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;TRACE:&lt;/strong&gt; 클라이언트의 요청을 그대로 반환하는 메서드. Ex) echo 서비스로 서버 상태를 확인하기 위한 목적으로 주로 사용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;요청 URI
    &lt;ul&gt;
      &lt;li&gt;요청하는 자원의 위치를 명시&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;HTTP 프로토콜 버전
    &lt;ul&gt;
      &lt;li&gt;웹 브라우저가 사용하는 프로토콜 버전&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Status&quot;&gt;응답 상태 코드&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;요청의 성공 여부 (200, 404 혹은 302)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;응답 메시지
    &lt;ul&gt;
      &lt;li&gt;상태 코드에 대한 이해를 돕기 위해 짧고 간결하게 상태 코드에 대한 설명을 글로 나타낸 것&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;url-uniform-resource-locator란&quot;&gt;URL (Uniform Resource Locator)란&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;URL이란
    &lt;ul&gt;
      &lt;li&gt;인터넷 상의 자원의 위치&lt;/li&gt;
      &lt;li&gt;특정 웹 서버의 특정 파일에 접근하기 위한 경로 혹은 주소&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;URL의 표현
    &lt;ul&gt;
      &lt;li&gt;접근 프로토콜 :// IP 주소 또는 도메인 이름 (:포트번호) / 자원의 경로 / 자원의 이름&lt;/li&gt;
      &lt;li&gt;Ex) http://www.example.co.kr/test/index.html&lt;/li&gt;
      &lt;li&gt;Ex) http://localhost:8080&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;mark&gt;TIP&lt;/mark&gt; URI와 URL의 차이
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;URI&lt;/strong&gt; (Uniform Resource Identifier)
        &lt;ul&gt;
          &lt;li&gt;요청하는 자원의 식별자 (규약)&lt;/li&gt;
          &lt;li&gt;자원을 고유하게 식별하고 위치를 지정할 수 있다.&lt;/li&gt;
          &lt;li&gt;URI의 하위 개념으로 URL이 포함된다. 즉, URI &amp;gt; URL&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;URL&lt;/strong&gt; (Uniform Resource Locator)
        &lt;ul&gt;
          &lt;li&gt;특정 웹 서버의 특정 자원에 대한 구체적인 위치 (규약의 형태)&lt;/li&gt;
          &lt;li&gt;자원의 정확한 위치와 접근하기 위한 방법을 알려준다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) URL 이면서 URI인 경우
        &lt;ul&gt;
          &lt;li&gt;https://gmlwjd9405.github.io/tags.html&lt;/li&gt;
          &lt;li&gt;자원의 고유한 식별자이면서 구체적인 위치를 명시한 형태&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) URL이 아니면서 URI인 경우
        &lt;ul&gt;
          &lt;li&gt;https://gmlwjd9405.github.io/posts/132&lt;/li&gt;
          &lt;li&gt;https://gmlwjd9405.github.io/list?page=2
            &lt;ul&gt;
              &lt;li&gt;URL: https://gmlwjd9405.github.io/list&lt;/li&gt;
              &lt;li&gt;URI: URL + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?page=2&lt;/code&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;자원에 접근할 수 있는 위치는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://gmlwjd9405.github.io/list&lt;/code&gt;이며, 이를 URL이라고 할 수 있다.&lt;/li&gt;
          &lt;li&gt;하지만 원하는 자원을 얻기 위해서는 추가적인 식별자인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page=2&lt;/code&gt;가 필요하고 이를 포함한 내용까지가 URI라고 할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;쿠키와 세션의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://doooyeon.github.io/2018/09/10/cookie-and-session.html&quot;&gt;쿠키(Cookie)와 세션(Session) 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;구체적인 HTTP 헤더의 내용에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/01/28/http-header-types.html&quot;&gt;HTTP 헤더의 종류 및 항목&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;TCP 연결에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/09/19/tcp-connection.html&quot;&gt;TCP 3-way handshaking과 4-way handshaking&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://mygumi.tistory.com/139&quot;&gt;https://mygumi.tistory.com/139&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Status&quot;&gt;https://developer.mozilla.org/ko/docs/Web/HTTP/Status&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Messages&quot;&gt;https://developer.mozilla.org/ko/docs/Web/HTTP/Messages&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://joshua1988.github.io/web-development/web-protocols/&quot;&gt;https://joshua1988.github.io/web-development/web-protocols/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Wed, 17 Apr 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/04/17/what-is-http-protocol.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/04/17/what-is-http-protocol.html</guid>
        
        <category>network</category>
        
        <category>http</category>
        
        <category>ip</category>
        
        <category>port</category>
        
        <category>url</category>
        
        <category>uri</category>
        
        <category>header</category>
        
        
      </item>
    
      <item>
        <title>[DB] ORM이란</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;영속성(Persistence)이란&lt;/li&gt;
    &lt;li&gt;ORM(Object Relational Mapping)이란&lt;/li&gt;
    &lt;li&gt;ORM의 장단점&lt;/li&gt;
    &lt;li&gt;The Object-Relational Impedance Mismatch&lt;/li&gt;
    &lt;li&gt;Association(연관성)
      &lt;ul&gt;
        &lt;li&gt;One-To-One Relationship&lt;/li&gt;
        &lt;li&gt;One-To-Many Relationship&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;영속성persistence&quot;&gt;영속성(Persistence)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;데이터를 생성한 프로그램이 종료되더라도 사라지지 않는 데이터의 특성을 말한다.&lt;/li&gt;
  &lt;li&gt;영속성을 갖지 않는 데이터는 단지 메모리에서만 존재하기 때문에 프로그램을 종료하면 모두 잃어버리게 된다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Object Persistence(영구적인 객체)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;메모리 상의 데이터를 파일 시스템, 관계형 테이터베이스 혹은 객체 데이터베이스 등을 활용하여 영구적으로 저장하여 영속성 부여한다.&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;/images/database/orm-persistence.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;데이터를 데이터베이스에 저장하는 3가지 방법
        &lt;ul&gt;
          &lt;li&gt;1) JDBC (java에서 사용)&lt;/li&gt;
          &lt;li&gt;2) Spring JDBC (Ex. JdbcTemplate)&lt;/li&gt;
          &lt;li&gt;3) Persistence Framework (Ex. Hibernate, Mybatis 등)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Persistence Layer&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;프로그램의 아키텍처에서, 데이터에 영속성을 부여해주는 계층을 말한다.&lt;/li&gt;
      &lt;li&gt;JDBC를 이용하여 직접 구현할 수 있지만 Persistence framework를 이용한 개발이 많이 이루어진다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Persistence Framework&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;JDBC 프로그래밍의 복잡함이나 번거로움 없이 간단한 작업만으로 데이터베이스와 연동되는 시스템을 빠르게 개발할 수 있으며 안정적인 구동을 보장한다.&lt;/li&gt;
      &lt;li&gt;Persistence Framework는 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;SQL Mapper와 ORM&lt;/a&gt;으로 나눌 수 있다.
        &lt;ul&gt;
          &lt;li&gt;Ex) JPA, Hibernate, Mybatis 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;orm이란&quot;&gt;ORM이란&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;Object Relational Mapping, 객체-관계 매핑&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;객체와 관계형 데이터베이스의 데이터를 &lt;strong&gt;자동으로 매핑(연결)해주는 것&lt;/strong&gt;을 말한다.
    &lt;ul&gt;
      &lt;li&gt;객체 지향 프로그래밍은 &lt;strong&gt;클래스&lt;/strong&gt;를 사용하고, 관계형 데이터베이스는 &lt;strong&gt;테이블&lt;/strong&gt;을 사용한다.&lt;/li&gt;
      &lt;li&gt;객체 모델과 관계형 모델 간에 불일치가 존재한다.&lt;/li&gt;
      &lt;li&gt;ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터베이스 데이터 &amp;lt;—매핑—&amp;gt; Object 필드
    &lt;ul&gt;
      &lt;li&gt;객체를 통해 간접적으로 데이터베이스 데이터를 다룬다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Persistant API라고도 할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;Ex) JPA, Hibernate 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;orm의-장단점&quot;&gt;ORM의 장단점&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;장점
    &lt;ul&gt;
      &lt;li&gt;객체 지향적인 코드로 인해 더 직관적이고 &lt;strong&gt;비즈니스 로직에 더 집중&lt;/strong&gt;할 수 있게 도와준다.
        &lt;ul&gt;
          &lt;li&gt;ORM을 이용하면 SQL Query가 아닌 직관적인 코드(메서드)로 데이터를 조작할 수 있어 개발자가 객체 모델로 프로그래밍하는 데 집중할 수 있도록 도와준다.&lt;/li&gt;
          &lt;li&gt;선언문, 할당, 종료 같은 부수적인 코드가 없거나 급격히 줄어든다.&lt;/li&gt;
          &lt;li&gt;각종 객체에 대한 코드를 별도로 작성하기 때문에 코드의 가독성을 올려준다.&lt;/li&gt;
          &lt;li&gt;SQL의 절차적이고 순차적인 접근이 아닌 객체 지향적인 접근으로 인해 생산성이 증가한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;재사용 및 유지보수&lt;/strong&gt;의 편리성이 증가한다.
        &lt;ul&gt;
          &lt;li&gt;ORM은 독립적으로 작성되어있고, 해당 객체들을 재활용 할 수 있다.&lt;/li&gt;
          &lt;li&gt;때문에 모델에서 가공된 데이터를 컨트롤러에 의해 뷰와 합쳐지는 형태로 디자인 패턴을 견고하게 다지는데 유리하다.&lt;/li&gt;
          &lt;li&gt;매핑정보가 명확하여, ERD를 보는 것에 대한 의존도를 낮출 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;DBMS에 대한 종속성이 줄어든다.&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;객체 간의 관계를 바탕으로 SQL을 자동으로 생성하기 때문에 RDBMS의 데이터 구조와 Java의 객체지향 모델 사이의 간격을 좁힐 수 있다.&lt;/li&gt;
          &lt;li&gt;대부분 ORM 솔루션은 DB에 종속적이지 않다.&lt;/li&gt;
          &lt;li&gt;종속적이지 않다는것은 구현 방법 뿐만아니라 많은 솔루션에서 자료형 타입까지 유효하다.&lt;/li&gt;
          &lt;li&gt;프로그래머는 Object에 집중함으로 극단적으로 DBMS를 교체하는 거대한 작업에도 비교적 적은 리스크와 시간이 소요된다.&lt;/li&gt;
          &lt;li&gt;또한 자바에서 가공할경우 equals, hashCode의 오버라이드 같은 자바의 기능을 이용할 수 있고, 간결하고 빠른 가공이 가능하다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;단점
    &lt;ul&gt;
      &lt;li&gt;완벽한 ORM 으로만 서비스를 구현하기가 어렵다.
        &lt;ul&gt;
          &lt;li&gt;사용하기는 편하지만 설계는 매우 신중하게 해야한다.&lt;/li&gt;
          &lt;li&gt;프로젝트의 복잡성이 커질경우 난이도 또한 올라갈 수 있다.&lt;/li&gt;
          &lt;li&gt;잘못 구현된 경우에 속도 저하 및 심각할 경우 일관성이 무너지는 문제점이 생길 수 있다.&lt;/li&gt;
          &lt;li&gt;일부 자주 사용되는 대형 쿼리는 속도를 위해 SP를 쓰는등 별도의 튜닝이 필요한 경우가 있다.&lt;/li&gt;
          &lt;li&gt;DBMS의 고유 기능을 이용하기 어렵다. (하지만 이건 단점으로만 볼 수 없다 : 특정 DBMS의 고유기능을 이용하면 이식성이 저하된다.)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다.
        &lt;ul&gt;
          &lt;li&gt;이미 프로시저가 많은 시스템에선 다시 객체로 바꿔야하며, 그 과정에서 생산성 저하나 리스크가 많이 발생할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-object-relational-impedance-mismatch&quot;&gt;The Object-Relational Impedance Mismatch&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/database/orm-impedance-mismatch.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Granularity(세분성)
    &lt;ul&gt;
      &lt;li&gt;경우에 따라 데이터베이스에 있는 해당 테이블 수보다 더 많은 클래스를 가진 객체 모델을 가질 수 있다.&lt;/li&gt;
      &lt;li&gt;예를 들어, “사용자 세부 사항”에 대해 생각해보자.
        &lt;ul&gt;
          &lt;li&gt;코드 재사용과 유지보수를 위해 “Person”과 “Address”라는 &lt;strong&gt;두 개의 클래스&lt;/strong&gt;로 나눌 수 있다.&lt;/li&gt;
          &lt;li&gt;그러나 데이터베이스에는 person이라는 &lt;strong&gt;하나의 테이블&lt;/strong&gt;에 “사용자 세부 사항”을 저장할 수 있다.&lt;/li&gt;
          &lt;li&gt;이렇게 Object 2개와 Table 1개로 두 개의 갯수가 다를 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;1) Coarse Granularity(굵은/거친): PersonDetails Class&lt;/li&gt;
      &lt;li&gt;2) Fine Granularity(가는/세밀한): Persion Class, Address Class&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Inheritance(상속)
    &lt;ul&gt;
      &lt;li&gt;RDBMS는 객체지향 프로그래밍 언어의 자연적 패러다임인 상속과 유사한 것을 정의하지 않는다.&lt;/li&gt;
      &lt;li&gt;즉, 상속의 개념이 없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Identity(일치)
    &lt;ul&gt;
      &lt;li&gt;RDBMS는 ‘sameness’라는 하나의 개념을 정확히 정의하는데, 바로 ‘기본키(primary key)’이다.&lt;/li&gt;
      &lt;li&gt;그러나 자바에서는 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/10/06/java-==-and-equals.html&quot;&gt;객체 식별(a==b)과 객체 동일성(a.equales(b))&lt;/a&gt;을 모두 정의한다.&lt;/li&gt;
      &lt;li&gt;RDBMS에서는 PK가 같으면 서로 동일한 record로 정의하지만, Java에서는 주솟값이 같거나 내용이 같은 경우를 구분하여 정의한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Associations(연관성)
    &lt;ul&gt;
      &lt;li&gt;객체지향 언어는 객체 참조(reference)를 사용하는 연관성을 나타내는 반면, RDBMS는 연관성을 ‘외래키(foreign key)’로 나타낸다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;아래 참고&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Navigation(탐색/순회)
    &lt;ul&gt;
      &lt;li&gt;Java 및 RDBMS에서 객체에 액세스하는 방법은 근본적으로 다르다.&lt;/li&gt;
      &lt;li&gt;Java에서는 하나의 연결에서 다른 연결로 이동하면서 탐색/순회한다. (그래프 형태)
        &lt;ul&gt;
          &lt;li&gt;예를 들어, aUser.getBillingDetails().getAccountNumber()&lt;/li&gt;
          &lt;li&gt;이는 RDBMS에서 데이터를 검색하는 효율적인 방법이 아니다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;RDBMS에서는 일반적으로 SQL 쿼리 수를 최소화하고 JOIN을 통해 여러 엔터티를 로드하고 원하는 대상 엔터티를 선택(select)한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;association연관성&quot;&gt;Association(연관성)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Java에서의 객체 참조(Object References)
    &lt;ul&gt;
      &lt;li&gt;방향성이 있다. (Directional)
        &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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Employee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; 
      &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
      &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
      &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Department&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;department&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Employee -&amp;gt; Department&lt;/span&gt;
      &lt;span class=&quot;err&quot;&gt;…&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;/li&gt;
      &lt;li&gt;Java에서 양방향 관계가 필요한 경우 연관을 두 번 정의해야 한다.
        &lt;ul&gt;
          &lt;li&gt;즉, 서로 Reference를 가지고 있어야 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RDBMS의 외래키(Foreign Key)
    &lt;ul&gt;
      &lt;li&gt;FK와 테이블 Join은 관계형 데이터베이스 연결을 자연스럽게 만든다.&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;/images/database/db-join-example.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;방향성이 없다. (Direction-Less)
        &lt;div class=&quot;language-sql 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;k&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;INTO&lt;/span&gt; 
  &lt;span class=&quot;n&quot;&gt;EMPLOYEE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;department_id&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;FK&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;One-To-One Relationship&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;예를 들어, 각 학생은 고유한 주소를 가지고 있다고 하자.&lt;/li&gt;
      &lt;li&gt;RDBMS (방향성이 없다.)
&lt;img src=&quot;/images/database/orm-one-to-one-example.png&quot; alt=&quot;&quot; /&gt;
        &lt;ul&gt;
          &lt;li&gt;각 Student의 record는 서로 다른 Address record를 가리키고 이것은 일대일 매핑을 보여준다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Java Object (방향성이 있다.)
&lt;img src=&quot;/images/database/orm-one-to-one-example2.png&quot; alt=&quot;&quot; /&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Student&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Student -&amp;gt; Address&lt;/span&gt;
 &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addressId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zipcode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;err&quot;&gt;…&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;One-To-Many Relationship&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;예를 들어, 각 학생은 여러 개의 핸드폰을 가질 수 있다고 하자.&lt;/li&gt;
      &lt;li&gt;RDBMS (방향성이 없다.)
&lt;img src=&quot;/images/database/orm-one-to-many-example.png&quot; alt=&quot;&quot; /&gt;
        &lt;ul&gt;
          &lt;li&gt;각 Student의 record는 여러 개의 Phone record를 가리킬 수 있다. (일대다 매핑)&lt;/li&gt;
          &lt;li&gt;이 관계를 하나의 다른 Table(Relational Model)로 만들 수 있다.&lt;/li&gt;
          &lt;li&gt;One-To-Many를 구성하는 방법: 1) Join Table, 2) Join Column&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Java Object (방향성이 있다.)
&lt;img src=&quot;/images/database/orm-one-to-many-example2.png&quot; alt=&quot;&quot; /&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Student&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Phone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;studentPhoneNumbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Student -&amp;gt; Some Phones&lt;/span&gt;
 &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Phone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;phoneId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;phoneType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;phoneNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;err&quot;&gt;…&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;JDBC, JPA/Hibernate, Mybatis의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html&quot;&gt;JDBC, JPA/Hibernate, Mybatis의 차이&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;Spring Hibernate에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/02/04/spring-hibernate.html&quot;&gt;Spring Hibernate 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.incodom.kr/ORM#h_702209f3f35878a32ee91352ddc6bbe7&quot;&gt;ORM의 장단점&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 01 Feb 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/02/01/orm.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/02/01/orm.html</guid>
        
        <category>db</category>
        
        <category>orm</category>
        
        
      </item>
    
      <item>
        <title>[Network] HTTP 헤더의 종류 및 항목</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;HTTP 헤더 내 일반 헤더 (General Header) 항목을 이해한다.&lt;/li&gt;
    &lt;li&gt;HTTP 헤더 내 엔터티/개체 헤더 (Entity Header) 항목&lt;/li&gt;
    &lt;li&gt;HTTP 헤더 내 요청 헤더 (Request Header) 항목&lt;/li&gt;
    &lt;li&gt;HTTP 헤더 내 응답 헤더 (Response Header) 항목&lt;/li&gt;
    &lt;li&gt;HTTP 헤더 내 캐시/쿠키와 관련된 항목을 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;http-공통-헤더&quot;&gt;HTTP 공통 헤더&lt;/h2&gt;
&lt;p&gt;HTTP 헤더 내 일반 헤더 (General Header) 항목&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;요청 및 응답 메시지 모두에서 사용 가능한 일반 목적의(기본적인) 헤더 항목&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주요-항목들&quot;&gt;주요 항목들&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Date&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;HTTP 메시지를 생성한 일시 (RFC 1123에서 규정)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Date: Sat, 2 Oct 2018 02:00:12 GMT&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Connection&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;클라이언트와 서버 간 연결에 대한 옵션 설정(다소 모호한 복잡성 있음)&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Connection: close&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;현재 HTTP 메시지 직후에 TCP 접속을 끊는다는 것을 알린다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Connection: Keep-Alive&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;현재 TCP 커넥션을 유지한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cache-Control&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Pragma&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trailer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;http-엔티티-관련-헤더&quot;&gt;HTTP 엔티티 관련 헤더&lt;/h2&gt;
&lt;p&gt;HTTP 헤더 내 엔터티/개체 헤더 (Entity Header) 항목&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;요청 및 응답 메시지 모두에서 사용 가능한 Entity(콘텐츠, 본문, 리소스 등)에 대한 설명 헤더 항목
    &lt;ul&gt;
      &lt;li&gt;HTTP 메시지 내 포함된 선택적인 개체에 대한 구체적인 미디어 타입 등의 설명&lt;/li&gt;
      &lt;li&gt;HTTP 메시지는 이미지, 비디오, 오디오, HTML 문서, 전자메일 등의 개체들을 운반할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주요-항목들-1&quot;&gt;주요 항목들&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Content-Type&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 개체에 포함되는 미디어 타입 정보&lt;/li&gt;
      &lt;li&gt;컨텐츠의 타입(MIME 미디어 타입) 및 문자 인코딩 방식(EUC-KR,UTF-8 등)을 지정한다.&lt;/li&gt;
      &lt;li&gt;타입 및 서브타입(type/subtype)으로 구성된다.
        &lt;ul&gt;
          &lt;li&gt;타입(type): 10개 정도 표준으로 지정됨(application, audio, font, image, multipart 등)&lt;/li&gt;
          &lt;li&gt;서브타입(subtype): 각 타입별로 수십에서 수백개 정도&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Type: text/html; charset-latin-1&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;해당 개체가 html 텍스트 문서이고, iso-latin-1 문자 인코딩 방식으로 표현되는 것을 의미한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Language&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 개체와 가장 잘 어울리는 사용자 언어(자연언어)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Encoding&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 개체 데이터의 압축 방식&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Encoding: gzip, deflate&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;만일 압축이 시행되었다면 Content-Encoding 및 Content-Length 2개 항목을 토대로 압축 해제가 가능하다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Length&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;전달되는 해당 개체의 바이트 길이 또는 크기(10진수)&lt;/li&gt;
      &lt;li&gt;응답 메시지 Body의 길이를 지정하거나 특정 지정된 개체의 길이를 지정한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Location&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 개체의 실제 위치를 알려준다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Disposition&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;응답 Body를 브라우저가 어떻게 표시해야할지 알려준다.&lt;/li&gt;
      &lt;li&gt;inline인 경우 웹페이지 화면에 표시되고, attachment인 경우 다운로드한다.
        &lt;ul&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Disposition: inline&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Disposition: attachment; filename='filename.csv'&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;다운로드되길 원하는 파일은 attachment로 값을 설정하고, filename 옵션으로 파일명까지 지정해줄 수 있다.&lt;/li&gt;
      &lt;li&gt;파일용 서버인 경우 이 태그를 자주 사용한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Security-Policy&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;다른 외부 파일들을 불러오는 경우, 차단할 소스와 불러올 소스를 명시한다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;XSS 공격&lt;/em&gt;에 대한 방어 가능 (허용한 외부 소스만 지정 가능)&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy: default-src https:&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;https를 통해서만 파일을 가져온다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy: default-src 'self'&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;자신의 도메인의 파일들만 가져온다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Security-Policy: default-src 'none'&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;파일을 가져올 수 없다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Location&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;리소스가 리다이렉트(redirect)된 때에 이동된 주소, 또는 새로 생성된 리소스 주소를 명시한다.&lt;/li&gt;
      &lt;li&gt;300번대 응답이나 201 Created 응답일 때 어느 페이지로 이동할지를 알려준다.
        &lt;ul&gt;
          &lt;li&gt;새로 생성된 리소스의 경우
            &lt;ul&gt;
              &lt;li&gt;HTTP 상태 코드 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;201 Created&lt;/code&gt;가 반환된다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;300번대 응답의 경우
            &lt;ul&gt;
              &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP/1.1 302 Found  Location: /&lt;/code&gt;&lt;/li&gt;
              &lt;li&gt;이런 응답이 왔다면 브라우저는 / 주소로 redirect한다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Last-Modified&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;리소스를 마지막으로 갱신한 일시&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transfer-Encoding&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;chuncked&lt;/li&gt;
      &lt;li&gt;동적으로 생성되어 Body의 길이를 모르는 경우에 조금씩 전송이 가능하다.&lt;/li&gt;
      &lt;li&gt;각 chunk 마다 그 시작에 16진수 길이를 삽입하여 chunk 길이를 알려준다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;http-요청-헤더&quot;&gt;HTTP 요청 헤더&lt;/h2&gt;
&lt;p&gt;HTTP 헤더 내 요청 헤더 (Request Header) 항목&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;요청 헤더는 HTTP 요청 메시지 내에서만 나타나며 가장 방대하다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주요-항목들-2&quot;&gt;주요 항목들&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Host&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;요청하는 호스트에 대한 호스트명 및 포트번호 (&lt;em&gt;필수&lt;/em&gt;)
        &lt;ul&gt;
          &lt;li&gt;HTTP/1.1 이후부터 Host 필드는 필수 항목이다. (웹브라우저는 이를 반드시 포함해야 함)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Host 필드에 도메인명 및 호스트명 모두를 포함한 전체 URI(FQDN) 지정이 필요하다.&lt;/li&gt;
      &lt;li&gt;이에 따라 동일 IP 주소를 갖는 단일 서버에 여러 사이트를 구축할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;User-Agent&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;클라이언트 소프트웨어(브라우저, OS) 명칭 및 버전 정보&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;From&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;클라이언트 사용자 메일 주소
        &lt;ul&gt;
          &lt;li&gt;주로 검색엔진 웹 로봇의 연락처 메일 주소를 나타낸다.&lt;/li&gt;
          &lt;li&gt;때로는, 이 연락처 메일 주소를 User-Agent 항목에 두는 경우도 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cookie&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버에 의해 Set-Cookie로 클라이언트에게 설정된 쿠키 정보&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Referer&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;바로 직전에 머물었던 웹 링크 주소&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;If-Modified-Since&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;제시한 일시 이후로만 변경된 리소스를 취득 요청&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Authorization&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;인증 토큰(JWT/Bearer 토큰)을 서버로 보낼 때 사용하는 헤더&lt;/li&gt;
      &lt;li&gt;“토큰의 종류(Basic, Bearer 등) + 실제 토큰 문자”를 전송&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Origin&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버로 POST 요청을 보낼 때, 요청이 어느 주소에서 시작되었는지 나타낸다.&lt;/li&gt;
      &lt;li&gt;여기서 요청을 보낸 주소와 받는 주소가 다르면 &lt;em&gt;CORS 에러&lt;/em&gt;가 발생한다.&lt;/li&gt;
      &lt;li&gt;응답 헤더의 &lt;strong&gt;Access-Control-Allow-Origin&lt;/strong&gt;와 관련&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;다음 4개는 주로 HTTP 메세지 Body의 속성 또는 내용 협상용 항목들
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Accept&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;클라이언트 자신이 원하는 미디어 타입 및 우선순위를 알린다.
            &lt;ul&gt;
              &lt;li&gt;텍스트(text/html,text/plain,…),이미지(image/jpeg,…) 등&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept: */*&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;어떤 미디어 타입도 가능하다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept: image/*&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;모든 이미지 유형이 가능하다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Accept-Charset&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;클라이언트 자신이 원하는 문자 집합&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Accept-Encoding&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;클라이언트 자신이 원하는 문자 인코딩 방식&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Accept-Language&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;클라이언트 자신이 원하는 가능한 언어&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;각각이 HTTP Entity Header 항목 중에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Type, Content-Type charset-xxx, Content-Encoding, Content-Language&lt;/code&gt;과 일대일로 대응된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예시&quot;&gt;예시&lt;/h3&gt;
&lt;div class=&quot;language-js 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;nx&quot;&gt;GET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;home&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;developer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mozilla&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;org&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mozilla&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Macintosh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Intel&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mac&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OS&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;rv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Gecko&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20100101&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Firefox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhtml&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.9&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;sr&quot;&gt;/ *;q=0.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;8
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Language&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;US&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gzip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;deflate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;br&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Referer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//developer.mozilla.org/testpage.html&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alive&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Upgrade&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Insecure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Requests&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;nx&quot;&gt;If&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Modified&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Since&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Jul&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2016&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;04&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GMT&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;If&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;c561c68d0ba92bbeb8b0fff2a9199f722e3a621a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Control&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-js 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;nx&quot;&gt;POST&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.1&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;developer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mozilla&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;org&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mozilla&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Macintosh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Intel&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mac&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OS&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;rv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Gecko&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20100101&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Firefox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;50.0&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;http-응답-헤더&quot;&gt;HTTP 응답 헤더&lt;/h2&gt;
&lt;p&gt;HTTP 헤더 내 응답 헤더 (Response Header) 항목&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;특정 유형의 HTTP 요청이나 특정 HTTP 헤더를 수신했을 때, 이에 응답한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;주요-항목들-3&quot;&gt;주요 항목들&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Server&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버 소프트웨어 정보&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Accept-Range&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Set-Cookie&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버측에서 클라이언트에게 세션 쿠키 정보를 설정 (RFC 2965에서 규정)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Expires&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;리소스가 지정된 일시까지 캐시로써 유효함을 나타낸다. 즉, 응답 컨텐츠가 언제 만료되는지를 나타낸다.&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expires: Thu, 26 Jul 2018 07:28:00 GMT&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Cache-Control과 별개로 응답에 Expires라는 헤더를 줄 수 있다.
        &lt;ul&gt;
          &lt;li&gt;단, Cache-Control의 max-age가 있는 경우 이 헤더는 무시&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Age&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;캐시 응답. max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려준다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ETag&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(쿠키/캐시 관련)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Proxy-authenticate&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Allow&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;해당 엔터티에 대해 서버 측에서 지원 가능한 HTTP 메소드의 리스트를 나타낸다.&lt;/li&gt;
      &lt;li&gt;때론, HTTP 요청 메세지의 HTTP 메소드 OPTIONS에 대한 응답용 항목으로 사용된다.
        &lt;ul&gt;
          &lt;li&gt;OPTIONS: 웹서버측 제공 HTTP 메소드에 대한 질의&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Allow: GET,HEAD&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;405 Method Not Allowed 에러와 함께&lt;/li&gt;
          &lt;li&gt;웹 서버에서 제공 가능한 HTTP 메서드는 GET, HEAD 뿐임을 알린다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Access-Control-Allow-Origin&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;요청을 보내는 프론트 주소와 받는 백엔드 주소가 다르면 &lt;em&gt;CORS 에러&lt;/em&gt;가 발생
        &lt;ul&gt;
          &lt;li&gt;서버에서 이 헤더에 프론트 주소를 적어주어야 에러가 나지 않는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Allow-Origin: www.zerocho.com&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;프로토콜, 서브도메인, 도메인, 포트 중 하나만 달라도 CORS 에러가 난다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Allow-Origin: *&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;만약 주소를 일일이 지정하기 싫다면 *으로 모든 주소에 CORS 요청을 허용되지만 그만큼 보안이 취약해진다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;유사한 헤더로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Headers&lt;/code&gt; 등이 있다.&lt;/li&gt;
      &lt;li&gt;Request와 Allow에서 Method 단수 복수 주의&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;예시-1&quot;&gt;예시&lt;/h3&gt;
&lt;div class=&quot;language-js 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;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OK&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Access&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Control&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Allow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Origin&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;nx&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Keep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Alive&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gzip&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;utf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Jul&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2016&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;06&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GMT&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Etag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;c561c68d0ba92bbeb8b0f612a9199f722e3a621a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Keep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Alive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;997&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Last&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Modified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Jul&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2016&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;04&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GMT&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Apache&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mykey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Mon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Jul&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2017&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;06&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GMT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;31449600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/; secur&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;e
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Transfer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;chunked&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Vary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Encoding&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Backend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;developer2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;webapp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scl3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mozilla&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;com&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cacheable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;meta&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;too&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;large&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;kuma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1085259&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DENY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt; &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Access_control_CORS&quot;&gt;CORS(Cross-Origin Resource Sharing)란?&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;배경
    &lt;ul&gt;
      &lt;li&gt;처음 전송되는 리소스의 도메인과 다른 도메인으로부터 리소스가 요청될 경우 해당 리소스는 cross-origin HTTP 요청에 의해 요청된다.&lt;/li&gt;
      &lt;li&gt;보안 상의 이유로, 브라우저들은 스크립트 내에서 초기화되는 cross-origin HTTP 요청을 제한한다.
        &lt;ul&gt;
          &lt;li&gt;예를 들면, XMLHttpRequest는 same-origin 정책을 따르기에 XMLHttpRequest을 사용하는 웹 애플리케이션은 자신과 동일한 도메인으로 HTTP 요청을 보내는 것만 가능했다.&lt;/li&gt;
          &lt;li&gt;웹 애플리케이션을 개선시키기 위해, 개발자들은 브라우저 벤더사들에게 XMLHttpRequest가 cross-domain 요청을 할 수 있도록 요청했고 이에 따라 CORS가 생겼다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;개념
    &lt;ul&gt;
      &lt;li&gt;웹 서버에게 보안 cross-domain 데이터 전송을 활성화하는 cross-domain 접근 제어권을 부여한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;과정
    &lt;ul&gt;
      &lt;li&gt;CORS 요청 시에는 미리 OPTIONS 주소로 서버가 CORS를 허용하는지 물어본다.&lt;/li&gt;
      &lt;li&gt;이때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Request-Method&lt;/code&gt;로 실제로 보내고자 하는 메서드를 알리고,&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Request-Headers&lt;/code&gt;로 실제로 보내고자 하는 헤더들을 알린다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Allow&lt;/code&gt; 항목들은 Request에 대응되는 것으로, 서버가 허용하는 메서드와 헤더를 응답하는데 사용된다.&lt;/li&gt;
      &lt;li&gt;Request랑 Allow가 일치하면 CORS 요청이 이루어진다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;http-캐시쿠키-관련-헤더&quot;&gt;HTTP 캐시/쿠키 관련 헤더&lt;/h2&gt;
&lt;h3 id=&quot;caching-관련&quot;&gt;Caching 관련&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Cache-Control&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: no-store&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;아무것도 캐싱하지 않는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: no-cache&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;모든 캐시를 쓰기 전에 서버에 해당 캐시를 사용해도 되는지 확인한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: must-revalidate&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;만료된 캐시만 서버에 확인을 받도록 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: public&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;공유 캐시(또는 중개 서버)에 저장해도 된다는 것을 의미한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: private&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;브라우저같은 특정 사용자 환경에만 저장한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control: max-age&lt;/code&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;strong&gt;&lt;em&gt;(공통 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Expires&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;리소스가 지정된 일시까지 캐시로써 유효함을 나타낸다. 즉, 응답 컨텐츠가 언제 만료되는지를 나타낸다.&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expires: Thu, 26 Jul 2018 07:28:00 GMT&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Cache-Control과 별개로 응답에 Expires라는 헤더를 줄 수 있다.
        &lt;ul&gt;
          &lt;li&gt;단, Cache-Control의 max-age가 있는 경우 이 헤더는 무시&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Age&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;캐시 응답. max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려준다.&lt;/li&gt;
      &lt;li&gt;Ex) max-age= 3600을 설정한 경우, 1분 후 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Age: 60&lt;/code&gt;이 캐시 응답 헤더에 포함된다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ETag&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그&lt;/li&gt;
      &lt;li&gt;같은 주소의 자원이더라도 컨텐츠가 달라졌다면 ETag가 다르다.&lt;/li&gt;
      &lt;li&gt;같은 주소로 GET 메서드 수행 시 응답 Body의 내용이 동일하면 같은 ETag를 갖지만, 내용이 바뀌었다면 ETag 헤더 값이 변경된다.&lt;/li&gt;
      &lt;li&gt;이 헤더 값이 변경되었다면 캐시를 지우고 새로 변경된 컨텐츠를 받는다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;If-None-Match&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버에 ETag가 달라졌는지 검사를 요청한다.&lt;/li&gt;
      &lt;li&gt;ETag가 다를 경우에만 컨텐츠를 새로 받는다.&lt;/li&gt;
      &lt;li&gt;만약 ETag가 같다면 서버는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;304 Not Modified&lt;/code&gt;를 응답해서 캐시를 그대로 사용한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(요청 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;cookies-관련&quot;&gt;Cookies 관련&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Cookie&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버에 의해 Set-Cookie로 클라이언트에게 설정된 쿠키 정보&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cookie: attribute1=value1; attribute2=value2;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;서버는 이 쿠키 헤더를 파싱해서 사용한다.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;CSRF 공격&lt;/em&gt; 같은 것을 막기 위해서 반드시 서버는 쿠키가 제대로 된 상황에서 온 것인지 확인하는 로직이 필요하다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(요청 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Set-Cookie&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;서버측에서 클라이언트에게 세션 쿠키 정보를 설정할 때 사용하는 항목 (RFC 2965에서 규정)&lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set-Cookie: 속성이름(attribute)=속성값(value); 옵션들&lt;/code&gt; 형태로 다수 정보들이 설정됨&lt;/li&gt;
      &lt;li&gt;옵션들
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;Expires&lt;/strong&gt;
            &lt;ul&gt;
              &lt;li&gt;쿠키 만료 날짜 설정&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;Max-Age&lt;/strong&gt;
            &lt;ul&gt;
              &lt;li&gt;쿠키 수명 설정. Expires는 무시&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;Secure&lt;/strong&gt;
            &lt;ul&gt;
              &lt;li&gt;https에서만 쿠키가 전송된다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;HttpOnly&lt;/strong&gt;
            &lt;ul&gt;
              &lt;li&gt;자바스크립트에서 쿠키에 접근할 수 없다.&lt;/li&gt;
              &lt;li&gt;&lt;em&gt;XSS&lt;/em&gt; 요청을 막으려면 활성화해두는 것이 좋다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;Domain&lt;/strong&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;strong&gt;Path&lt;/strong&gt;
            &lt;ul&gt;
              &lt;li&gt;해당 path와 일치하는 요청에서만 쿠키가 전송된다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Ex) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set-Cookie: zerocho=babo; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;쿠키는 &lt;em&gt;XSS 공격과 CSRF 공격&lt;/em&gt; 등에 취약하기 때문에 HttpOnly 옵션을 켜두고, 쿠키를 사용하는 요청은 서버 단에서 검증하는 로직을 마련해두는 것이 좋다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;em&gt;(응답 헤더)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt; 캐시, 쿠키, 세션의 차이&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ktword.co.kr/abbr_view.php?nav=&amp;amp;m_temp1=469&amp;amp;id=492&quot;&gt;캐시 (Cache)&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;개념
        &lt;ul&gt;
          &lt;li&gt;CPU와 주기억장치 사이에 물리적으로 존재하는 버퍼 형태의 고속의 기억장치를 말한다. (통상, 컴퓨터 메모리 버퍼를 지칭)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;사용 목적
        &lt;ul&gt;
          &lt;li&gt;CPU와 주기억장치 사이의 속도의 차이를 완화 (메모리 읽기 속도 개선용)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;쿠키 (Cookie)
    &lt;ul&gt;
      &lt;li&gt;개념
        &lt;ul&gt;
          &lt;li&gt;인터넷 웹 상에서 상태정보를 클라이언트측(인터넷 웹브라우저)에 저장하여, 서버측에서 필요할 때마다 지속성있게 활용하고자 할 때 사용한다. (클라이언트 로컬에 저장되는 키와 값이 들어있는 파일)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;사용 목적
        &lt;ul&gt;
          &lt;li&gt;HTTP의 비연결(Connectionless)과 무상태(Stateless)을 보완&lt;/li&gt;
          &lt;li&gt;웹 브라우저에 서버측에 있는 상태값들을 저장할 수 있게하도록 하여 사용자에 대한 지속적인 상태감시 및 상태참조를 한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;쿠키 저장
        &lt;ul&gt;
          &lt;li&gt;웹 서버는, HTTP 헤더 내 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set-Cookie:&lt;/code&gt;란에 셋팅할 쿠키 관련 정보를 실려 보낸다.&lt;/li&gt;
          &lt;li&gt;웹 브라우저는, 쿠키를 도메인 서버 이름으로 정렬된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;쿠키 디렉토리&lt;/code&gt;에 저장한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;세션(Session)
    &lt;ul&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;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;쿠키와 세션의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://doooyeon.github.io/2018/09/10/cookie-and-session.html&quot;&gt;쿠키(Cookie)와 세션(Session) 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP&quot;&gt;mozilla - HTTP 이해하기&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.ktword.co.kr/abbr_view.php?nav=&amp;amp;m_temp1=5905&amp;amp;id=902&quot;&gt;http://www.ktword.co.kr/abbr_view.php?nav=&amp;amp;m_temp1=5905&amp;amp;id=902&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.ktword.co.kr/abbr_view.php?nav=&amp;amp;m_temp1=469&amp;amp;id=492&quot;&gt;http://www.ktword.co.kr/abbr_view.php?nav=&amp;amp;m_temp1=469&amp;amp;id=492&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.zerocho.com/category/HTTP/post/5b594dd3c06fa2001b89feb9&quot;&gt;https://www.zerocho.com/category/HTTP/post/5b594dd3c06fa2001b89feb9&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://zamezzz.tistory.com/137&quot;&gt;cors - https://zamezzz.tistory.com/137&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Access_control_CORS&quot;&gt;cors - https://developer.mozilla.org/ko/docs/Web/HTTP/Access_control_CORS&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Mon, 28 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/28/http-header-types.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/28/http-header-types.html</guid>
        
        <category>network</category>
        
        <category>http</category>
        
        <category>header</category>
        
        <category>types</category>
        
        
      </item>
    
      <item>
        <title>[Spring] Spring MVC and Spring Boot Structure</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Spring MVC Structure를 이해한다.&lt;/li&gt;
    &lt;li&gt;Spring Boot Structure를 이해한다.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;참고용!&lt;/strong&gt; &lt;mark&gt;'내가' 사용하는 프로젝트 구조이므로, 개발자마다 설정 방법에 따라 구조가 달라질 수 있다.&lt;/mark&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;spring-mvc-structure&quot;&gt;Spring MVC Structure&lt;/h2&gt;
&lt;h3 id=&quot;ㄴsrcmainjava&quot;&gt;ㄴsrc/main/java&lt;/h3&gt;
&lt;p&gt;: 자바 소스 파일&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;class(Servlet)
    &lt;ul&gt;
      &lt;li&gt;controller package&lt;/li&gt;
      &lt;li&gt;service package&lt;/li&gt;
      &lt;li&gt;dao package&lt;/li&gt;
      &lt;li&gt;model package&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ㄴsrcmainresources&quot;&gt;ㄴsrc/main/resources&lt;/h3&gt;
&lt;p&gt;: 자바 소스 파일에서 사용하는 리소스 파일(mapper, sql, logging 등 설정 파일)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;logback.xml&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ㄴweb-또는-webapp&quot;&gt;ㄴweb (또는 webapp)&lt;/h3&gt;
&lt;p&gt;: Web에서 사용하는 리소스 파일(static files, templates, xml, properties 등)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;static or &lt;del&gt;resources&lt;/del&gt; DIR
    &lt;ul&gt;
      &lt;li&gt;css, images, fonts, js..&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;WEB-INF
    &lt;ul&gt;
      &lt;li&gt;props or database DIR
        &lt;ul&gt;
          &lt;li&gt;jdbc.properties&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;views
        &lt;ul&gt;
          &lt;li&gt;includes DIR
            &lt;ul&gt;
              &lt;li&gt;header / footer / layout&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;jsp or html&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;web.xml&lt;/li&gt;
      &lt;li&gt;XXXconfig.xml
        &lt;ul&gt;
          &lt;li&gt;applicationContext.xml&lt;/li&gt;
          &lt;li&gt;dispatcher-servlet.xml&lt;/li&gt;
          &lt;li&gt;serviceContext.xml&lt;/li&gt;
          &lt;li&gt;daoContext.xml&lt;/li&gt;
          &lt;li&gt;securityContext.xml&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ㄴpomxml&quot;&gt;ㄴpom.xml&lt;/h3&gt;
&lt;p&gt;: Maven 프로젝트 설정 파일&lt;/p&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;
  &lt;li&gt;Property 관리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;/WEB-INF 디렉토리 이하는 보안상의 문제로 웹 브라우저를 통한 접근을 금지하고 있다.
    &lt;ul&gt;
      &lt;li&gt;하지만 포워딩을 통한 접근은 웹 브라우저를 통하지 않기 때문에 가능하다.&lt;/li&gt;
      &lt;li&gt;컴파일된 클래스, 스프링 환경 설정 파일(DB 연결 정보), jsp 등 외부에서의 수정 방지&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;정적 자원들은 /static 디렉터리 사용을 권장한다.&lt;/li&gt;
  &lt;li&gt;dispatcher-servlet.xml
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;mvc:resources mapping=&quot;/static/**&quot; location=&quot;/static/&quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;web/static/&lt;/li&gt;
      &lt;li&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;/&lt;/strong&gt;&lt;/span&gt;는 “web/” location을 의미한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;applicationContext.xml
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;context:property-placeholder location=&quot;classpath:props/jdbc.properties&quot;/&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;web/WEB-INF/props/jdbc.properties&lt;/li&gt;
      &lt;li&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;classpath:&lt;/strong&gt;&lt;/span&gt;는 “web/WEB-INF/” location을 의미한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;spring-boot&quot;&gt;Spring Boot&lt;/h2&gt;
&lt;h3 id=&quot;ㄴsrcmainjava-1&quot;&gt;ㄴsrc/main/java&lt;/h3&gt;
&lt;p&gt;: 자바 소스 파일&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;class(Servlet)
    &lt;ul&gt;
      &lt;li&gt;web package (controller)&lt;/li&gt;
      &lt;li&gt;service package&lt;/li&gt;
      &lt;li&gt;repository package (dao)&lt;/li&gt;
      &lt;li&gt;domain package (model)&lt;/li&gt;
      &lt;li&gt;dto package&lt;/li&gt;
      &lt;li&gt;config package&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- - security package
- validation package
- common package --&gt;

&lt;h3 id=&quot;ㄴsrcmainresources-1&quot;&gt;ㄴsrc/main/resources&lt;/h3&gt;
&lt;p&gt;: 배포할 리소스 파일(static files, templates, xml, properties 등)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;static
    &lt;ul&gt;
      &lt;li&gt;css, images, fonts, js..&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;templates
    &lt;ul&gt;
      &lt;li&gt;includes DIR
        &lt;ul&gt;
          &lt;li&gt;header / footer / layout&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;dynamic HTML&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;application-{profile}.properties or application.yml&lt;/li&gt;
  &lt;li&gt;import.sql&lt;/li&gt;
  &lt;li&gt;logback.xml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Spring Boot에서는 JSP 보다는 템플릿 엔진의 사용을 권장한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/12/21/template-engine.html&quot;&gt;템플릿 엔진의 개념과 종류 및 필요성&lt;/a&gt; 참고&lt;/li&gt;
      &lt;li&gt;JSP 사용을 위해서는 추가 설정이 필요하다.
&lt;!-- * 기본적으로 Spring Boot는 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;**classpath**&lt;span&gt;에 있는 /static(/public, /resources, /META-INF/resources) 디렉터리 또는 ServletContext의 루트로부터 정적 콘텐트를 서비스한다. --&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Spring Boot는 기본적으로 src/main/resources/ 디렉터리를 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;classpath&lt;/strong&gt;&lt;/span&gt;로 가지고 있다.&lt;/li&gt;
  &lt;li&gt;Spring Boot에서는 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;classpath&lt;/strong&gt;&lt;/span&gt; 상에서 /static, /resources, /public, /META-INF/resources/ 경로를 기본으로 탐색한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-static-content&quot;&gt;https://docs.spring.io&lt;/a&gt; 참고&lt;/li&gt;
      &lt;li&gt;/WEB-INF/resources의 경우, jar 파일로 배포할 경우에는 인식하지 않기 때문에 사용하지 않도록 주의한다.&lt;/li&gt;
      &lt;li&gt;정적 자원들은 /static 디렉터리 사용을 권장한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Spring Boot에서는 기존의 전통적인 웹 어플리케이션 방식에서 필수로 관리되어야 하는 Tomcat 설정 및 web.xml 파일 등은 스프링부트의 내부 모듈에 의해서 구동시 자동으로 설정된다. &lt;br /&gt; &lt;strong&gt;(default로 web/ 디렉터리가 없음)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;MVC Architecture에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/11/05/mvc-architecture.html&quot;&gt;MVC Architecture 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;Spring MVC Framework에 대해 알고 싶으시면 &lt;a href=&quot;http://gmlwjd9405.github.io/2018/12/20/spring-mvc-framework.html&quot;&gt;Spring MVC 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://gist.github.com/ihoneymon/a343e2f4a0299988206e&quot;&gt;https://gist.github.com/ihoneymon/a343e2f4a0299988206e&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://lazyrodi.github.io/2017/09/03/2017-09-03-spring-structure/&quot;&gt;http://lazyrodi.github.io/2017/09/03/2017-09-03-spring-structure/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sat, 05 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/05/spring-directory-structure.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/05/spring-directory-structure.html</guid>
        
        <category>springMVC</category>
        
        <category>spring</category>
        
        <category>springBoot</category>
        
        <category>structure</category>
        
        <category>web</category>
        
        
      </item>
    
      <item>
        <title>[Logging] SLF4J를 이용한 Logging</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Logging이란&lt;/li&gt;
    &lt;li&gt;SLF4J(Simple Logging Facade for Java)란
      &lt;ul&gt;
        &lt;li&gt;1) SLF4J API&lt;/li&gt;
        &lt;li&gt;2) SLF4J Binding&lt;/li&gt;
        &lt;li&gt;3) SLF4J Bridging Modules&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;SLF4J 특징&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;logging이란&quot;&gt;Logging이란&lt;/h1&gt;
&lt;p&gt;프로그램 개발 중이나 완료 후 발생할 수 있는 오류에 대해 디버깅하거나 운영 중인 프로그램 상태를 모니터링 하기 위해 필요한 정보(로그)를 기록하는 것&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;애플리케이션 실행에 대한 추적을 기록하기 위해 어딘가에 메시지 (콘솔, 파일, 데이터베이스 등)를 작성하는 것&lt;/li&gt;
  &lt;li&gt;Logging을 어디에 이용할까
    &lt;ul&gt;
      &lt;li&gt;디버깅&lt;/li&gt;
      &lt;li&gt;사용자 상호 작용 기록 (발생하는 이벤트 기록)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Java의 주요 Logging Framework
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;native java.util.logging&lt;/strong&gt;: 별로 사용하지 않는다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Log4J&lt;/strong&gt;: 몇 년 전까지 사실상 표준으로 사용했다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Logback&lt;/strong&gt;: Log4J 개발자가 만든 Log4J의 후속 버전, 현재 많은 프로젝트에서 사용되고 있다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;SLF4J(Simple Logging Facade for Java)&lt;/strong&gt;: Log4J 또는 Logback과 같은 백엔드 Logger Framework의 &lt;em&gt;facade pattern&lt;/em&gt;(아래 참고)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;tinylog&lt;/strong&gt;: 사용하기 쉽게 최적화된 Java용 최소형(75KB Jar) 프레임워크&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;vs-debuggger&quot;&gt;VS Debuggger&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;장점
    &lt;ul&gt;
      &lt;li&gt;Logging은 응용 프로그램 실행에 대한 정확한 컨텍스트(이벤트 순서)를 제공한다.
        &lt;ul&gt;
          &lt;li&gt;전체적인 app의 흐름이나 타이밍 error도 확인할 수 있다.&lt;/li&gt;
          &lt;li&gt;error 종류: 논리적 에러, 타이밍 에러(multi-thread) 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;일단 코드에 삽입되면 logging output이 만들어질 때 사용자 개입이 필요 없다.&lt;/li&gt;
      &lt;li&gt;로그 출력은 나중에 살펴볼 수 있도록 영구 매체에 저장할 수 있다.
        &lt;ul&gt;
          &lt;li&gt;disk에 기록을 남겨 유용한 로깅 정보를 추적할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Logging Framework는 Debuggger보다 간단하고 배우기 쉽고 사용하기 쉽다.&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;ul&gt;
          &lt;li&gt;메시지 level을 나누는 기능&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;고급 사용은 구성을 확실히 알아야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;vs-plain-outputsystemoutprintln&quot;&gt;VS Plain Output(System.out.println())&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;장점
    &lt;ul&gt;
      &lt;li&gt;높은 유연성&lt;/li&gt;
      &lt;li&gt;우선순위 level 이상의 출력 메시지를 선택할 수 있다.
        &lt;ul&gt;
          &lt;li&gt;—trace, debug, info, warn, error—&amp;gt; high&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;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;출력 위치를 지정할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;slf4jsimple-logging-facade-for-java란&quot;&gt;SLF4J(Simple Logging Facade for Java)란&lt;/h1&gt;
&lt;p&gt;Log4J 또는 Logback과 같은 백엔드 Logging Framework의 &lt;em&gt;facade pattern&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;다양한 Logging Framework에 대한 추상화
    &lt;ul&gt;
      &lt;li&gt;SLF4J는 추상 로깅 프레임워크이기 때문에 단독으로는 사용하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SLF4J api를 사용하면 구현체의 종류에 상관없이 일관된 로깅 코드를 작성할 수 있다.&lt;/li&gt;
  &lt;li&gt;배포할 때 원하는 Logging Framework를 선택할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;Ex) logback/log4j/jdk14 - SLF4J - app&lt;/li&gt;
      &lt;li&gt;개발할 때, SLF4J API를 사용하여 로깅 코드를 작성한다.&lt;/li&gt;
      &lt;li&gt;배포할 때, 바인딩된 Logging Framework가 실제 로깅 코드를 수행한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;교환 가능
    &lt;ul&gt;
      &lt;li&gt;Logging Framework 간에 쉬운 전환이 가능하다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SLF4J는 세 가지 모듈을 제공한다. (&lt;strong&gt;API / Binding / Bridging&lt;/strong&gt;)
    &lt;ol&gt;
      &lt;li&gt;SLF4J API 활성화
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;slf4j-api-1.7.25.jar&lt;/strong&gt; (2017년 기준)&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;slf4j-api-1.8.0-beta2.jar&lt;/strong&gt; (2019년 기준)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;SLF4J 바인딩(.jar)
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;SLF4J 인터페이스를 로깅 구현체와 연결&lt;/strong&gt;하는 어댑터 역할을 하는 라이브러리&lt;/li&gt;
          &lt;li&gt;사용하길 원하는 Logging Framework에 대한 SLF4J 바인딩을 추가해야 한다. &lt;br /&gt;(반드시 &lt;strong&gt;한개만&lt;/strong&gt; 사용)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;SLF4J Bridging Modules
        &lt;ul&gt;
          &lt;li&gt;다른 로깅 API로의 Logger 호출을 &lt;strong&gt;SLF4J 인터페이스로 연결(redirect)&lt;/strong&gt;하여 &lt;strong&gt;SLF4J API가 대신 처리&lt;/strong&gt;할 수 있도록 하는 일종의 어댑터 역할을 하는 라이브러리&lt;/li&gt;
          &lt;li&gt;다른 로깅 API -&amp;gt; Bridge(redirect) -&amp;gt; SLF4J API&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt; &lt;em&gt;facade pattern&lt;/em&gt;
&lt;img src=&quot;/images/logging/facade-pattern.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;여러 개의 클래스가 하나의 역할을 수행할 때, 대표적인 인터페이스만을 다루는 클래스를 두어 원하는 기능을 처리할수 있게 도와주는 패턴이다.
    &lt;ul&gt;
      &lt;li&gt;클라이언트는 Facade에 요청을 전송하여 Subsystem과 통신하며, Facade는 해당 요청을 적절한 Subsystem 객체로 전달한다.
        &lt;ul&gt;
          &lt;li&gt;Subsystem 객체가 실제 작업을 수행하지만 Facade는 인터페이스를 Subsystem 인터페이스로 변환하기 위해 자체 작업을 수행해야 할 수도 있다.&lt;/li&gt;
          &lt;li&gt;즉, 공통된 Interface를 적절하게 변환해서 연결한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Facade를 사용하는 클라이언트는 Subsystem 객체에 직접 액세스할 필요가 없다.
        &lt;ul&gt;
          &lt;li&gt;즉, 클라이언트는 Subsystem을 알 필요 없이 Common Interface에만 접근한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;1-slf4j-api---hello-world-using-slf4j&quot;&gt;1) SLF4J API - “Hello World” using SLF4J&lt;/h2&gt;
&lt;h3 id=&quot;1-class-path에-slf4j-api-1725jar-추가-pomxml&quot;&gt;1. class path에 slf4j-api-1.7.25.jar 추가 (pom.xml)&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;slf4j-api&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.25&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-helloworld-클래스를-컴파일하고-실행&quot;&gt;2. HelloWorld 클래스를 컴파일하고 실행&lt;/h3&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.slf4j.Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.slf4j.LoggerFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HelloWorld&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&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;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&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;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&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;err&quot;&gt; &lt;/span&gt; &lt;span class=&quot;err&quot;&gt; &lt;/span&gt;   
        &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoggerFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;HelloWorld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; &lt;/span&gt;  
    &lt;span class=&quot;o&quot;&gt;}&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;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;SLF4J: Failed to load class &quot;org.slf4j.impl.StaticLoggerBinder&quot;. 
SLF4J: Defaulting to no-operation (NOP) logger implementation 
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;이 경고는 class path에서 slf4j 구현체를 찾을 수 없기 때문에 출력된다.
    &lt;ul&gt;
      &lt;li&gt;즉, class path에 사용하길 원하는 Logging Framework에 대한 slf4j 바인딩(.jar)을 추가해야 한다.&lt;/li&gt;
      &lt;li&gt;이때, 둘 이상의 slf4j 바인딩(반드시 &lt;strong&gt;하나만&lt;/strong&gt;)을 두면 안된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Logging Framework를 전환하려면 class path에서 slf4j 바인딩을 변경한다.
    &lt;ul&gt;
      &lt;li&gt;Ex) java.util.logging —&amp;gt; log4j로 전환하려면&lt;/li&gt;
      &lt;li&gt;slf4j-&lt;strong&gt;jdk14&lt;/strong&gt;-1.7.25.jar —&amp;gt; slf4j-&lt;strong&gt;log4j12&lt;/strong&gt;-1.7.25.jar로 변경&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-slf4j-binding&quot;&gt;2) SLF4J Binding&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;SLF4J 인터페이스를 로깅 구현체(Logging Framework)와 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;연결하는 어댑터 역할&lt;/span&gt;을 하는 라이브러리&lt;/li&gt;
  &lt;li&gt;SLF4J binding with a Logging Framework
    &lt;ul&gt;
      &lt;li&gt;각각의 SLF4J binding(.jar)은 &lt;strong&gt;&lt;em&gt;compile time&lt;/em&gt;&lt;/strong&gt;에 오직 하나의 Logging Framework를 사용하도록 바인딩한다.&lt;/li&gt;
      &lt;li&gt;class path에서 바인딩된 구현체가 발견되지 않으면 slf4j는 기본적으로 no-operation으로 설정된다. (즉, 출력되는 것이 없음)&lt;/li&gt;
      &lt;li&gt;사용하길 원하는 Logging Framework에 대한 SLF4J 바인딩을 추가해야 한다.
&lt;img src=&quot;/images/logging/logging-framework-flow.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;slf4j-binding-종류&quot;&gt;SLF4J binding 종류&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;사용하길 원하는 Logging Framework에 대한 SLF4J 바인딩을 추가해야 한다. (반드시 &lt;strong&gt;한개만&lt;/strong&gt; 사용)&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;SLF4J binding(.jar)&lt;/strong&gt;)&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;slf4j-log4j12-{version}.jar&lt;/td&gt;
      &lt;td&gt;널리 사용되는 로깅 프레임워크인 log4j 버전 1.2에 대한 바인딩. &lt;br /&gt; 또한 log4j.jar을 클래스 경로에 배치해야 한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;slf4j-jdk14-{version}.jar&lt;/td&gt;
      &lt;td&gt;java.util.logging(JDK1.4 로깅)에 대한 바인딩.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;slf4j-nop-{version}.jar&lt;/td&gt;
      &lt;td&gt;NOP에 대한 바인딩. 모든 로깅을 자동으로 삭제합니다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;slf4j-simple-{version}.jar&lt;/td&gt;
      &lt;td&gt;모든 이벤트를 System.err에 출력하는 단순 구현 바인딩. &lt;br /&gt; INFO 이상의 메시지만 출력되므로 작은 응용 프로그램에서 유용하다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;slf4j-jcl-{version}.jar&lt;/td&gt;
      &lt;td&gt;JCL(Jakarta Commons Logging)에 대한 바인딩. &lt;br /&gt; 모든 SLF4J 로깅을 JCL에 위임한다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;logback-classic-{version}.jar&lt;/td&gt;
      &lt;td&gt;(logback-core-{version}.jar 필요) &lt;strong&gt;native implement&lt;/strong&gt; &lt;br /&gt; Logback의 클래스는 SLF4J의 인터페이스를 직접 구현한 것으로, SLF4J 프로젝트 외부에 SLF4J 바인딩이 있다. &lt;br /&gt; 따라서 Logback과 함께 SLF4J를 사용하면 메모리 및 오버헤드가 발생하지 않는다. &lt;br /&gt; Logback의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ch.qos.logback.classic.Logger&lt;/code&gt; 클래스는 SLF4J의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.slf4j.Logger&lt;/code&gt; 인터페이스를 직접 구현한 것이다.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;예시: SLF4J binding with Logback&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;기본 Logging Framework로 logback-classic을 사용하려면&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;ch.qos.logback&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;logback-classic&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.2.3&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;exclusions&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;exclusion&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;slf4j-api&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exclusion&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/exclusions&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;compile&lt;span class=&quot;nt&quot;&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;ch.qos.logback&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;logback-core&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.2.3&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;slf4j-api&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.25&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;pom.xml에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ch.qos.logback:logback-classic&quot;&lt;/code&gt; dependency 추가
    &lt;ul&gt;
      &lt;li&gt;이 dependency 하나만 추가해도 된다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logback-classic&lt;/code&gt;가 의존하는 logback-core-1.2.3.jar뿐만 아니라 slf4j-api-1.7.25.jar를 자동으로 가져온다.&lt;/li&gt;
      &lt;li&gt;하지만 해당 artifact의 올바른 버전을 사용하는데 필요하기 때문에 모두 &lt;strong&gt;명시적으로 선언&lt;/strong&gt;하는 것이 좋다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;애플리케이션 레이어에서 SLF4J를 사용해서 Logging 코드를 작성하면 실제 로그를 출력하는 행위는 Logback이 하게 된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3-slf4j-bridging-modules&quot;&gt;3) SLF4J Bridging Modules&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;(SLF4J 이외의) 다른 로깅 API로의 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;Logger 호출을 SLF4J 인터페이스로 연결(redirect)&lt;/span&gt;하여 SLF4J API가 대신 처리할 수 있도록 하는 일종의 어댑터 역할을 하는 라이브러리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.slf4j.org/manual.html&quot;&gt;Consolidate logging via SLF4J&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;프로젝트는 다양한 components로 구성된다.
    &lt;ul&gt;
      &lt;li&gt;components 중 일부는 SLF4J 이외의 로깅 API에 의존한다.&lt;/li&gt;
      &lt;li&gt;Ex) spring-context는 JCL(Jarkarta Commons Logging) API를 사용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이러한 상황을 처리하기 위해 SLF4J에는 여러 &lt;strong&gt;Bridging Module&lt;/strong&gt;이 제공된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.slf4j.org/legacy.html&quot;&gt;Bridging legacy logging APIs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;여러 다른 로깅 API를 사용하는 components에 대해 single channel을 통해 Logging을 통합하는 것이 바람직하다.&lt;/li&gt;
  &lt;li&gt;이를 위해 SLF4J에서 log4j API, JCL(Jakarta Commons Logging) API 및 JUL(Java Util Logging) API에 대한 호출을 대신 SLF4J API에 대한 것처럼 리디렉션하는 여러 &lt;strong&gt;Bridging Modules&lt;/strong&gt;을 제공한다.
&lt;img src=&quot;/images/logging/bridge-for-binding.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;!-- xxx-over-slf4j는 SLF4J가 지원하는 로깅을 대신 구현해주는 이름들입니다. 
 결과적으로 자신이 고칠수 없는 소스를 그대로 두고 SLF4J를 사용하는것처럼 바꿀수 있는 방법입니다. 
 쉽게 말해 각각 로깅 구현체를 SLF4J가 package이름으로 구현을 해놓은 것입니다.  --&gt;&lt;/p&gt;

&lt;h3 id=&quot;slf4j가-제공하는-bridge의-종류&quot;&gt;SLF4J가 제공하는 Bridge의 종류&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;겉으로는 다른 로깅 API를 사용하는 것 같지만 내부에서는 SLF4J API를 호출하도록 일종의 어댑터 역할을 해주는 라이브러리
    &lt;ul&gt;
      &lt;li&gt;다른 로깅 API -&amp;gt; Bridge -&amp;gt; SLF4J API&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;SLF4J binding(.jar)&lt;/strong&gt;)&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;jcl-over-slf4j.jar&lt;/td&gt;
      &lt;td&gt;JCL API에 의존하는 클래스들을 손상시키지 않고 JCL로 들어오는 호출을 JCL-over-SLF4J를 이용해서 SLF4J API를 호출한다. &lt;br /&gt; 즉, 이 모듈을 사용하면 JCL을 사용하는 기존 소프트웨어와의 호환성을 손상시키지 않으면서 프로젝트를 SLF4J로 단편적으로 마이그레이션할 수 있다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;log4j-over-slf4j.jar&lt;/td&gt;
      &lt;td&gt;이 모듈을 사용하면 log4j 호출을 SLF4J API로 리디렉션할 수 있다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;jul-to-slf4j.jar&lt;/td&gt;
      &lt;td&gt;이 모듈을 사용하면 java.util.logging 호출을 SLF4J API로 리디렉션할 수 있다.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;ul&gt;
  &lt;li&gt;사용 시 주의할 점&lt;/li&gt;
  &lt;li&gt;&lt;img src=&quot;/images/logging/bridge-infinite-loop.png&quot; alt=&quot;&quot; /&gt;
    &lt;ul&gt;
      &lt;li&gt;jcl-over-slf4j.jar
        &lt;ul&gt;
          &lt;li&gt;JCL API 사용 X —&amp;gt; 의존성에서 commons-logging.jar 제거&lt;/li&gt;
          &lt;li&gt;SLF4J Binding인 &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-jcl-{version}.jar&lt;/code&gt;&lt;/strong&gt;와 같이 쓸 수 없다. (무한루프)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;log4j-over-slf4j.jar
        &lt;ul&gt;
          &lt;li&gt;Log4J API 사용 X —&amp;gt; 의존성에서 log4j.jar 제거&lt;/li&gt;
          &lt;li&gt;SLF4J Binding인 &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-log4j12-{version}.jar&lt;/code&gt;&lt;/strong&gt;와 같이 쓸 수 없다. (무한루프)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;jul-to-slf4j.jar
        &lt;ul&gt;
          &lt;li&gt;java.util.logging은 교체 불가능 (LogRecord 객체를 사용해서 위임)&lt;/li&gt;
          &lt;li&gt;SLF4J Binding인 &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-jdk14-{version}.jar&lt;/code&gt;&lt;/strong&gt;와 같이 쓸 수 없다. (무한루프)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;mark&gt;참고&lt;/mark&gt; JCL(Jakarta Commons Logging)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Log4j, LogKit, JDK1.4과 같은 다른 Logging Framework에 대한 추상화 계층을 제공하는 인터페이스&lt;/li&gt;
  &lt;li&gt;로깅 라이브러리가 아니라 로깅 &lt;strong&gt;추상화&lt;/strong&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;실제 Logging Framework을 선택하는 시점이 &lt;strong&gt;&lt;em&gt;runtime&lt;/em&gt;&lt;/strong&gt;이라 클래스 로더 문제
        &lt;ul&gt;
          &lt;li&gt;클래스 로더에 의존적인 방법으로 구현체(Logging Framework)를 찾는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;런타임 시 오버헤드&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;예시: Logging with SLF4J and Logback&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;img src=&quot;/images/logging/loggin-with-slf4j-logback.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;필요한 라이브러리&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;... 
    위의 SLF4J binding with Logback 내용과 동일 
    logback-classic
    logback-core
    slf4j-api
...
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;log4j-over-slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.25&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jcl-over-slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.25&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jul-to-slf4j&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.25&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ol&gt;
  &lt;li&gt;SLF4J API (인터페이스)
    &lt;ul&gt;
      &lt;li&gt;로깅에 대한 추상 레이어를 제공&lt;/li&gt;
      &lt;li&gt;사용자가 이 interface를 통해 로깅 코드를 작성한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-api&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SLF4J Binding(.jar)
    &lt;ul&gt;
      &lt;li&gt;SLF4J 인터페이스를 로깅 구현체로 연결하는 어댑터 역할을 하는 라이브러리&lt;/li&gt;
      &lt;li&gt;SLF4J에 구현체(Logging Framework)를 바인딩하기 위해 사용한다.&lt;/li&gt;
      &lt;li&gt;여러 바인딩 중 하나만 사용할 것&lt;/li&gt;
      &lt;li&gt;[Logback] &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logback-classic&lt;/code&gt;&lt;/strong&gt; / [Log4J] &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-log4j12&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Logging Framework
    &lt;ul&gt;
      &lt;li&gt;실제 로깅 코드를 실행할 Logging Framework를 정한다.&lt;/li&gt;
      &lt;li&gt;[Logback] &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logback-core&lt;/code&gt;&lt;/strong&gt; / [Log4J] &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-core&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;SLF4J Bridging Module
    &lt;ul&gt;
      &lt;li&gt;다른 로깅 API -&amp;gt; Bridge(redirect) -&amp;gt; SLF4J API&lt;/li&gt;
      &lt;li&gt;다른 로깅 API로의 Logger 호출을 SLF4J 인터페이스로 연결(redirect)하여 SLF4J API가 대신 처리할 수 있도록 하는 일종의 어댑터 역할을 하는 라이브러리&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log4j-over-slf4j&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcl-over-slf4j&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jul-to-slf4j&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;Logging Framework를 변경하고 싶으면 2, 3번을 교체&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;slf4j-특징&quot;&gt;SLF4J 특징&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;배포시 Logging Framework 선택 가능
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;compile time&lt;/em&gt;에 오직 하나의 Logging Framework를 사용하도록 바인딩&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;빠른 속도로 작동
    &lt;ul&gt;
      &lt;li&gt;클래스가 JVM에 의해 로드되는 방식으로 인해 프레임워크 바인딩은 초기에 자동으로 확인된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;널리 사용되는 Logging Framework를 위한 바인딩 제공
    &lt;ul&gt;
      &lt;li&gt;log4j, java.util.logging, 단순 로깅 및 NOP를 지원&lt;/li&gt;
      &lt;li&gt;logback 프로젝트는 기본적으로 SLF4J를 지원&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Bridging legacy logging API
    &lt;ul&gt;
      &lt;li&gt;log4j API, JCL(Jakarta Commons Logging) API 및 java.util.logging API에 대한 호출을 대신 SLF4J API에 대한 것처럼 리디렉션하는 여러 Bridging Modules을 제공&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Migrate your source code
    &lt;ul&gt;
      &lt;li&gt;SLF4J-Migrator utility를 사용하면 SLF4J를 사용하는 소스를 마이그레이션할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;매개 변수화된 로그 메시지 지원&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;SLF4J의 개념과 설정 방법에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html&quot;&gt;SLF4J를 이용한 Logging&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.slf4j.org/manual.html&quot;&gt;https://www.slf4j.org/manual.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://stackify.com/compare-java-logging-frameworks/&quot;&gt;https://stackify.com/compare-java-logging-frameworks/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.slideshare.net/whiteship/ss-47273947&quot;&gt;스프링 부트와 로깅 slideshare&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://whiteship.me/?p=12162&quot;&gt;http://whiteship.me/?p=12162&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://sonegy.wordpress.com/2014/05/23/how-to-slf4j/&quot;&gt;https://sonegy.wordpress.com/2014/05/23/how-to-slf4j/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 04 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html</guid>
        
        <category>logging</category>
        
        <category>slf4j</category>
        
        <category>bridge</category>
        
        <category>binding</category>
        
        <category>usage</category>
        
        
      </item>
    
      <item>
        <title>[Spring] Spring Security</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Spring Security란&lt;/li&gt;
    &lt;li&gt;Spring Security 사용법
      &lt;ul&gt;
        &lt;li&gt;1) 필요한 Library&lt;/li&gt;
        &lt;li&gt;2) Spring Security 활성화&lt;/li&gt;
        &lt;li&gt;3) Spring Security 설정&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;(참고) Expression-Based Access Control&lt;/li&gt;
    &lt;li&gt;(참고) Custom Login/Logout Form&lt;/li&gt;
    &lt;li&gt;Spring Security Architecture (전체 과정)&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;spring-security란&quot;&gt;Spring Security란&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;스프링 기반 애플리케이션의 보안을 위한 사실상의 표준
&lt;img src=&quot;/images/spring-framework/springsecurity-overview1.png&quot; alt=&quot;&quot; /&gt;
    &lt;ul&gt;
      &lt;li&gt;Spring Security는 전적으로 Servlet Filter를 기반으로 한다.&lt;/li&gt;
      &lt;li&gt;Filter는 (Servlet과 브라우저 사이에서 주고 받는) 요청과 응답을 가로 채고, 해당 요청/응답 전후에서 필요한 처리를 할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;사용자 정의가 가능한 인증 및 접근제어/권한 프레임워크
    &lt;ul&gt;
      &lt;li&gt;authientication(인증): id/pw, 공인인증서 등&lt;/li&gt;
      &lt;li&gt;authorization(권한): admin, user, guest 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;간략한 과정
    &lt;ul&gt;
      &lt;li&gt;&lt;img src=&quot;/images/spring-framework/springsecurity-overview2.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Authorization&lt;/strong&gt;(권한): 권한이 없는 User가 접근할 경우, 자동으로 Login Page를 띄어준다.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Authentication&lt;/strong&gt;(인증): 사용자가 입력한 id/pw가 일치하는지 Authentication Providers(DB)를 통해 확인한다.&lt;/li&gt;
  &lt;li&gt;id/pw가 일치하지 않으면 1, 2번을 반복한다.&lt;/li&gt;
  &lt;li&gt;인증과 권한이 통과가 되면 Secured Area에 접근을 허용한다.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;spring-security-사용법&quot;&gt;Spring Security 사용법&lt;/h1&gt;
&lt;h2 id=&quot;1-필요한-library&quot;&gt;1. 필요한 Library&lt;/h2&gt;
&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;org.springframework-version&amp;gt;&lt;/span&gt;5.1.3.RELEASE&lt;span class=&quot;nt&quot;&gt;&amp;lt;/org.springframework-version&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;org.springsecurity-version&amp;gt;&lt;/span&gt;4.2.3.RELEASE&lt;span class=&quot;nt&quot;&gt;&amp;lt;/org.springsecurity-version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.security&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-security-core&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${org.springsecurity-version}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.security&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-security-web&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${org.springsecurity-version}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.security&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-security-config&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${org.springsecurity-version}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;사용하는 버전에 주의한다. (여기서는 Spring Security 4를 기준으로 작성)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-spring-security-활성화&quot;&gt;2. Spring Security 활성화&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Spring Security는 &lt;strong&gt;DelegatingFilterProxy&lt;/strong&gt;를 사용한다.
    &lt;ul&gt;
      &lt;li&gt;DelegatingFilterProxy는 모든 요청을 가로채는 Filter이다.&lt;/li&gt;
      &lt;li&gt;이 Filter를 &lt;strong&gt;web.xml&lt;/strong&gt;에 추가한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;filter&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;springSecurityFilterChain&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-class&amp;gt;&lt;/span&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-class&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-mapping&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;springSecurityFilterChain&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt;/*&lt;span class=&quot;nt&quot;&gt;&amp;lt;/url-pattern&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-mapping&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;filter-name&amp;gt;&lt;/code&gt; : 이 이름으로 등록된다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;filter-class&amp;gt;&lt;/code&gt; : Filter로 사용할 클래스&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;filter-mapping&amp;gt;&lt;/code&gt; : 위에서 설정한 Filter 이름과 url을 mapping한다. (“/*”: 모든 request)&lt;/li&gt;
  &lt;li&gt;이 Filter를 이용하면 Spring이 요청을 가로채서 해당 사용자의 인증, 권한을 알아서 확인해준다.
    &lt;ul&gt;
      &lt;li&gt;사용자가 입력한 정보와 DB에 저장되어 있는 정보를 비교한 후 알아서 인증, 권한을 확인한다.&lt;/li&gt;
      &lt;li&gt;단, App마다 달라지는 부분은 우리(개발자)가 알아서 처리한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3-spring-security-설정&quot;&gt;3. Spring Security 설정&lt;/h2&gt;
&lt;h3 id=&quot;webxml-설정&quot;&gt;web.xml 설정&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- web.xml --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;context-param&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-name&amp;gt;&lt;/span&gt;contextConfigLocation&lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-name&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-value&amp;gt;&lt;/span&gt;
        /WEB-INF/applicationContext.xml
        /WEB-INF/securityContext.xml 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-value&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/context-param&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;listener&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;listener-class&amp;gt;&lt;/span&gt;org.springframework.web.context.ContextLoaderListener&lt;span class=&quot;nt&quot;&gt;&amp;lt;/listener-class&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/listener&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;web.xml의 contextConfigLocation에 securityContext.xml을 추가한다.
    &lt;ul&gt;
      &lt;li&gt;그래야 나중에 ContextLoaderListener에 의해 등록된 설정 파일을 읽을 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;securitycontextxml-설정&quot;&gt;securityContext.xml 설정&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/spring-framework/springsecurity-securitycontext.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;# 1. beans에 추가할 설정&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- securityContext.xml --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;beans&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.springframework.org/schema/beans&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;xmlns:security=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.springframework.org/schema/security&quot;&lt;/span&gt;
       &lt;span class=&quot;na&quot;&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
       
       ...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;beans에 추가할 설정
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmlns:security=&quot;http://www.springframework.org/schema/security&quot;&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;내가 설정한 약어: security&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xsi:schemaLocation=&quot;http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd&quot;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;# 2. Authentication(인증) 설정&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- Authentication(인증) 설정 --&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!--방법 1. User Authentication with In-Memory definition--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;security:authentication-manager&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:authentication-provider&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:user-service&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1234&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;authorities=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ROLE_ADMIN&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:user&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;testUser&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;password=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;authorities=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ROLE_USER&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:user-service&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:authentication-provider&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:authentication-manager&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!--방법 2. Other Authentication Provider (Using Database)--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;security:authentication-manager&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:authentication-provider&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:jdbc-user-service&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;data-source-ref=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dataSource&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;users-by-username-query=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;select username, password, enabled from users where username=?&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;authorities-by-username-query=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;select username, authority from authorities where username=?&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:authentication-provider&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:authentication-manager&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;authentication-manager&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;요청의 인증을 처리한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;authentication-provider&amp;gt;&lt;/code&gt;가 제공하는 메커니즘을 사용하여 사용자를 인증한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;인증 처리를 할 사용자 정보를 가져오는 방법 &lt;span style=&quot;background-color: #e1e1e1&quot;&gt;2가지&lt;/span&gt;
    &lt;ul&gt;
      &lt;li&gt;1) 메모리&lt;/li&gt;
      &lt;li&gt;2) DB&lt;/li&gt;
      &lt;li&gt;모두 있어도 상관없다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:user-service&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;test를 위해 &lt;strong&gt;메모리 상&lt;/strong&gt;에 일시적으로 하드 코드된 사용자를 정의한다.
        &lt;ul&gt;
          &lt;li&gt;이름은 “admin”, 비밀번호는 “1234”인 사용자에게 “ROLE_ADMIN” 권한 부여&lt;/li&gt;
          &lt;li&gt;이름은 “admtestUserin”, 비밀번호는 “test”인 사용자에게 “ROLE_USER” 권한 부여&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:jdbc-user-service&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;DB에&lt;/strong&gt; 사용자 계정 정보를 저장한다.
        &lt;ul&gt;
          &lt;li&gt;&lt;img src=&quot;/images/spring-framework/springsecurity-table-design.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
          &lt;li&gt;table은 개발자가 설계한다.&lt;/li&gt;
          &lt;li&gt;여기서는 계정 정보 테이블과 권한 정보 테이블을 만들었다.&lt;/li&gt;
          &lt;li&gt;이 정보들은 사용자가 회원가입할 때 저장해야하는 정보들이다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-source-ref=&quot;dataSource&quot;&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;DB 접근을 위한 명시&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;데이터베이스 정보를 추출하기 위해 수행할 구체적인 쿼리를 정의한다.
        &lt;ul&gt;
          &lt;li&gt;아래의 쿼리는 Default로 설정되어 있다. (명시하지 않아도 됨)
            &lt;ul&gt;
              &lt;li&gt;Spring Security가 인증, 권한을 확인하기 위한 사용자의 정보들을 가져오기 위해서 Spring에게 해당 쿼리문을 수행하라고 명시하는 것이다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;1) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users-by-username-query=&quot;select username, password, enabled from users where username=?&quot;&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;사용자가 입력한 username 정보를 바탕으로 인증을 위한 username, password, enabled 정보를 가져온다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;2) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorities-by-username-query=&quot;select username, authority from authorities where username=?&quot;&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;사용자가 입력한 username 정보를 바탕으로 접근 제어를 위한 authority(권한 정보)을 가져온다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;이후에는 사용자가 입력한 정보와 DB에 저장되어 있는 정보를 비교하여 Spring Security가 &lt;strong&gt;알아서&lt;/strong&gt; 인증, 권한을 확인한다&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;# 3. Authorization(권한)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- Authorization(권한) 설정 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;security:http&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;auto-config=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;use-expressions=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/secured/**&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hasRole('ROLE_USER')&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/admin/**&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hasRole('ROLE_ADMIN')&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/login&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;permitAll()&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;permitAll()&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/resources/**&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;permitAll()&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:intercept-url&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;pattern=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/**&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;access=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;denyAll()&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;security:form-login&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;login-page=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/login&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/security:http&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auto-config=&quot;true&quot;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;form 기반 로그인, 기본 인증 및 로그 아웃 메커니즘을 자동으로 활성화한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use-expressions=&quot;true&quot;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Spring EL Expressions 사용을 활성화한다. &lt;strong&gt;&lt;em&gt;&lt;mark&gt;(아래 참고)&lt;/mark&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:intercept-url&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;보안이 필요한 요청 URL에 대한 패턴을 정의한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access&lt;/code&gt; 속성(use-expressions)
        &lt;ul&gt;
          &lt;li&gt;해당 패턴과 일치하는 요청된 URL을 볼 수 있는 권한이 있는 사용자의 역할을 정의한다.&lt;/li&gt;
          &lt;li&gt;권한은 특정 사용자에게 할당된 역할 목록을 쉼표로 분리하여 사용할 수 있다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:form-login&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;default settings을 오버라이딩한다.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login-page=&quot;/login&quot;&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;Defalt 페이지인 Spring Login Form이 아닌 사용자가 정의한 Custom Login Form을 사용한다. &lt;strong&gt;&lt;em&gt;&lt;mark&gt;(아래 참고)&lt;/mark&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고-expression-based-access-control&quot;&gt;&lt;strong&gt;&lt;em&gt;&lt;mark&gt;(참고)&lt;/mark&gt;&lt;/em&gt;&lt;/strong&gt; Expression-Based Access Control&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Authorization(접근 제어) 메커니즘으로서 Spring EL Expressions를 사용한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Expression&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;hasRole([role])&lt;/td&gt;
      &lt;td&gt;현재 로그인한 주체(principal)가 권한을 가지고 있으면 true 반환&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;hasAnyRole([role1,role2])&lt;/td&gt;
      &lt;td&gt;현재 로그인한 주체가 제공된 권한 중 하나라도 가지고 있으면 true 반환 (쉼표로 여러 개의 권한 목록 지정 가능)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;principal&lt;/td&gt;
      &lt;td&gt;현재 로그인한 사용자를 나타내는 객체에 직접 액세스할 수 있다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;authentication&lt;/td&gt;
      &lt;td&gt;SecurityContext에서 얻은 현재 Authentication 객체에 직접 액세스할 수 있다.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;permitAll&lt;/td&gt;
      &lt;td&gt;모든 사용자 접근 가능 (Always evaluates to true)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;denyAll&lt;/td&gt;
      &lt;td&gt;모든 사용자 접근 불가능 (Always evaluates to false)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;isAnonymous()&lt;/td&gt;
      &lt;td&gt;현재 로그인한 사용자가 익명 사용자(anonymous user)인 경우 true 반환&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;isRememberMe()&lt;/td&gt;
      &lt;td&gt;현재 로그인한 사용자가 기억하고 있는 사용자(remember-me user)인 경우 true 반환&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;isAuthenticated()&lt;/td&gt;
      &lt;td&gt;현재 로그인한 사용자가 익명이 아닌 경우 true 반환 &lt;strong&gt;(인증만 되어 있으면 접근 허용)&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;isFullyAuthenticated()&lt;/td&gt;
      &lt;td&gt;현재 로그인한 사용자가 익명 또는 기억하고 있는 사용자가 아닌 경우 true 반환&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;참고-custom-loginlogout-form&quot;&gt;&lt;strong&gt;&lt;em&gt;&lt;mark&gt;(참고)&lt;/mark&gt;&lt;/em&gt;&lt;/strong&gt; Custom Login/Logout Form&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;default settings을 오버라이딩
      &lt;ul&gt;
        &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:form-login login-page=&quot;/login&quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;내가 정한 URL을 처리할 Login Controller(@GetMapping)을 만든다.&lt;/li&gt;
    &lt;li&gt;Custom Loing Page(login.jsp)를 만든다.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1-securitycontextxml-설정&quot;&gt;1. securityContext.xml 설정&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:form-login&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;default settings을 오버라이딩한다.&lt;/li&gt;
      &lt;li&gt;Defalt 페이지인 Spring Login Page가 아닌 사용자가 정의한 Custom Login Page를 사용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;security:form-login&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;login-page=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/login&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security:form-login&lt;/code&gt; attribute &lt;strong&gt;(Spring Security 4)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login-page=&quot;/login&quot;&lt;/code&gt;는 Spring Security을 지시한다.
        &lt;ul&gt;
          &lt;li&gt;인증 절차를 처리할 URL(/login)을 정한다.&lt;/li&gt;
          &lt;li&gt;개발자가 &lt;strong&gt;임의로 결정&lt;/strong&gt;할 수 있다.&lt;/li&gt;
          &lt;li&gt;접근 제어에 따라 사용자의 인증 절차가 필요한 경우 브라우저를 해당 URL(“/login”)으로 redirect한다.
            &lt;ul&gt;
              &lt;li&gt;return redirect:/login; [GET]&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;해당 요청을 처리할 LoginController는 로그인 페이지를 렌더링하는 login.jsp를 반환한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authentication-failure-url=&quot;/login?error&quot;&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;특별히 지정하지 않아도 Default로 설정되어 있다.
            &lt;ul&gt;
              &lt;li&gt;관례상 error &lt;strong&gt;=1&lt;/strong&gt;을 넣기도 한다.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;사용자가 잘못된 사용자 이름과 암호로 로그인하려고 하면 동일한 로그인 페이지로 가되, 인증 실패를 알리기 위해 URL 뒤에 error라는 request parameter를 붙여 성공과 구분한다.
            &lt;ul&gt;
              &lt;li&gt;즉, 인증 시도가 실패하면 브라우저를 “/login?error”로 redirect한다.&lt;/li&gt;
              &lt;li&gt;return redirect:/login?error; [GET]&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;마찬가지로 해당 요청을 처리할 LoginController는 실패 메시지를 Model에 담아 login.jsp를 반환한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security:logout&lt;/code&gt; attribute &lt;strong&gt;(Spring Security 4)&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;logout-success-url=&quot;/login?logout&quot;&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;특별히 지정하지 않아도 Default로 설정되어 있다.&lt;/li&gt;
          &lt;li&gt;사용자가 성공적으로 로그아웃하면 브라우저를 “/login?logout”로 redirect한다.
            &lt;ul&gt;
              &lt;li&gt;return redirect:/login?logout; [GET]&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;마찬가지로 해당 요청을 처리할 LoginController는 로그아웃 확인 메시지를 Model에 담아 login.jsp를 반환한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security:form-login&lt;/code&gt; attribute &lt;strong&gt;(Spring Security 4)&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Attribute&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Default value&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Note&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;login-page&lt;/td&gt;
      &lt;td&gt;/login&lt;/td&gt;
      &lt;td&gt;implement&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;username-parameter &lt;/td&gt;
      &lt;td&gt;username&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;password-parameter&lt;/td&gt;
      &lt;td&gt;password&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;login-processing-url&lt;/td&gt;
      &lt;td&gt;/login , POST&lt;/td&gt;
      &lt;td&gt;the URL used to process the login request by spring&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;authentication-failure-url&lt;/td&gt;
      &lt;td&gt;/login?error&lt;/td&gt;
      &lt;td&gt;implement&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security:logout&lt;/code&gt; attribute &lt;strong&gt;(Spring Security 4)&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Attribute&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Default value&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Note&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;logout-url &lt;/td&gt;
      &lt;td&gt;/logout, POST&lt;/td&gt;
      &lt;td&gt;Log out processing module by spring&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;logout-success-url&lt;/td&gt;
      &lt;td&gt;/login?logout&lt;/td&gt;
      &lt;td&gt;implement&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;2-controller&quot;&gt;2. Controller&lt;/h3&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;@Controller&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoginController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 사용자가 입력한 정보로부터 POST 요청은 Spring Security를 거친 후 해당 메서드로 들어온다.&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/login&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@RequestParam&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&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;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
                        &lt;span class=&quot;nd&quot;&gt;@RequestParam&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;logout&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&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;n&quot;&gt;logout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
                        &lt;span class=&quot;nc&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&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;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&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;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;errorMsg&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invalid username and password&quot;&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;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&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;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addAttribute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;logoutMsg&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;You have been logged out successfully&quot;&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;login&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// login.jsp(Custom Login Page)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&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;ul&gt;
  &lt;li&gt;POST 요청 —&amp;gt; Spring Security —redirect:(GET 요청)—&amp;gt; 내가 작성한 Controller
    &lt;ul&gt;
      &lt;li&gt;POST 요청은 Spring Security에 의해 처리&lt;/li&gt;
      &lt;li&gt;Spring Security가 “redirect:” 한 GET 요청은 내가 작성한 Controller에서 처리&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;인증 성공 시, &lt;strong&gt;redirect:/&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;HomeController - index.jsp(Main Page) 반환&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;인증 실패 시, &lt;strong&gt;redirect:/login?error&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;LoginController - 오류 메시지를 Model에 담아 login.jsp(Custom Login Page) 반환&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;로그아웃 성공 시, &lt;strong&gt;redirect:/login?logout&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;LoginController - 로그아웃 확인 메시지를 Model에 담아 login.jsp(Custom Login Page) 반환&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-custom-loing-page&quot;&gt;3. Custom Loing Page&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;home.jsp&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-html 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;c&quot;&gt;&amp;lt;!-- 로그인한 사용자가 있으면 LOGOUT이 보인다. --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${pageContext.request.userPrincipal.name != null}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;javascript:document.getElementById('logout').submit()&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;LOGOUT&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- logout processing module of spring security 4 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;logout&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;c:url value=&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;logout&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&quot; method=&quot;post&quot;&amp;gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${_csrf.parameterName}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${_csrf.token}&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;login.jsp&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-html 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;nt&quot;&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Custom Login with Username and Password&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- For logout  --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${not empty logoutMsg}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;color: #0000ff;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&amp;gt;&lt;/span&gt; ${logoutMsg} &lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- login processing module of spring security 4 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;c:url value=&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&quot; method=&quot;post&quot;&amp;gt;
&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- For failed user authentication  --&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;c:if&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;test=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${not empty errorMsg}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;color: #ff0000;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;h3&amp;gt;&lt;/span&gt; ${errorMsg} &lt;span class=&quot;nt&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/c:if&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;User:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'text'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'username'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&lt;/span&gt;Password:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'password'&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'password'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;colspan=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'2'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LOGIN&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${_csrf.parameterName}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${_csrf.token}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;login/logout processing module of spring security 4
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;action=&quot;&amp;lt;c:url value=&quot;/logout&quot; /&amp;gt;&quot;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;action=&quot;&amp;lt;c:url value=&quot;/login&quot; /&amp;gt;&quot;&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;spring security에 지정되어 있는 이름이기 때문에 위의 value는 변경하면 안된다.
    &lt;ul&gt;
      &lt;li&gt;즉, 개발자가 &lt;strong&gt;임의로 결정&lt;/strong&gt;할 수 없다.&lt;/li&gt;
      &lt;li&gt;버전마다 value가 다를 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;참고) CSRF(사이트 간 요청 위조, Cross-Site Request Forgery) attack
    &lt;ul&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;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;input type=&quot;hidden&quot; name=&quot;${_csrf.parameterName}&quot; value=&quot;${_csrf.token}&quot;/&amp;gt;&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;민감한 정보를 아둘 때 세션에 Token(임의의 난수)를 발급하여, 해당 난수가 없는 상황에서 해당 동작들이 이루어지면 요청을 거부한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;spring-security-architecture-전체-과정&quot;&gt;Spring Security Architecture (전체 과정)&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/images/spring-framework/springsecurity-total.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Authorization&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;securityContext.xml에 권한 설정 명시&lt;/li&gt;
      &lt;li&gt;권한이 없는 User가 접근할 경우,&lt;/li&gt;
      &lt;li&gt;Spring이 내부적으로 Defalt 페이지인 Spring Login Page로 redirect한다.&lt;/li&gt;
      &lt;li&gt;참고) 사용자가 설정한 Login Page로 redirect하는 경우, 설정 파일(securityContext.xml)의 권한 설정에 아래 내용 추가
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;security:form-login login-page=&quot;/login&quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Authentication&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;사용자가 입력한 id/pw가 일치하는지 Authentication Providers(DB)를 통해 확인한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;id/pw가 일치하지 않으면 1, 2번을 반복한다.&lt;/li&gt;
  &lt;li&gt;인증과 권한이 통과가 되면 Secured Area에 접근을 허용한다.
    &lt;ul&gt;
      &lt;li&gt;Login한 사용자가 인증, 권한에 대해 모두 성공하면 원래의 URL(Secured Page)로 redirect한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;사용자-동작에-따른-전체-과정-설명&quot;&gt;사용자 동작에 따른 전체 과정 설명&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;사용자 흐름에 따른 전체 과정 요약&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;사용자가 로그인 정보를 입력하고 Submit하면 &lt;em&gt;/login&lt;/em&gt; URL로 &lt;strong&gt;POST 요청&lt;/strong&gt;이 날아간다.&lt;/li&gt;
  &lt;li&gt;이후에는 Spring Security에 의해 Login/Logout Process를 거친다.
    &lt;ul&gt;
      &lt;li&gt;Spring Security가 인증 결과에 따라 적절하게 &lt;em&gt;redirect:&lt;/em&gt; 를 반환한다.
        &lt;ul&gt;
          &lt;li&gt;인증 성공 시, redirect:&lt;em&gt;/&lt;/em&gt;&lt;/li&gt;
          &lt;li&gt;인증 실패 시, redirect:&lt;em&gt;/login?error&lt;/em&gt;&lt;/li&gt;
          &lt;li&gt;로그아웃 성공 시, redirect:&lt;em&gt;/login?logout&lt;/em&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Controller에서 해당 redirect &lt;strong&gt;GET 요청&lt;/strong&gt;을 받아 처리한다.
    &lt;ul&gt;
      &lt;li&gt;인증 성공 시, HomeController에서 return index.jsp(Main Page)&lt;/li&gt;
      &lt;li&gt;인증 실패 시, LoginController에서 오류 메시지를 Model에 담아 return login.jsp(Custom Login Page)&lt;/li&gt;
      &lt;li&gt;로그아웃 성공 시, LoginController에서 로그아웃 확인 메시지를 Model에 담아 return login.jsp&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;참고) POST 요청 —&amp;gt; Spring Security —redirect:(GET 요청)—&amp;gt; 내가 작성한 Controller
    &lt;ul&gt;
      &lt;li&gt;POST 요청은 Spring Security에 의해 처리&lt;/li&gt;
      &lt;li&gt;Spring Security가 “redirect:” 한 GET 요청은 내가 작성한 Controller에서 처리&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;로그인 인증 성공/실패&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;home.jsp에서 Secured Page(Ex. Admin Page) 이동 클릭 [GET]&lt;/li&gt;
  &lt;li&gt;접근 제어에 따라 사용자 인증 절차 필요 (Ex. ROLE_ADMIN 사용자만 가능)
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login-page=&quot;/login&quot;&lt;/code&gt;에 의해 Spring Security가 브라우저를 “/login”로 redirect&lt;/li&gt;
      &lt;li&gt;참고) 이때, login-page의 URL은 &lt;strong&gt;&lt;em&gt;개발자가 임의로 정할 수 있다.&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;return redirect:/login; [GET]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;개발자가 작성한 &lt;strong&gt;LoginController&lt;/strong&gt; login method [GetMapping]
    &lt;ul&gt;
      &lt;li&gt;return login.jsp (Custom Login Page)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;login.jsp에서 사용자 정보 입력 후 LOGIN을 Submit [POST]
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;form action=&quot;&amp;lt;c:url value=&quot;/login&quot;/&amp;gt;&quot; method=&quot;post&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;참고) 이때, value 값은 &lt;strong&gt;&lt;em&gt;개발자가 임의로 정할 수 없다.&lt;/em&gt;&lt;/strong&gt; (spring security에 지정되어 있는 이름)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Spring Security&lt;/strong&gt; login method [PostMapping] 실행
    &lt;ul&gt;
      &lt;li&gt;인증 절차 성공:
        &lt;ul&gt;
          &lt;li&gt;redirect:/ [GET] (원래의 URL(Secured Page)로 redirect)&lt;/li&gt;
          &lt;li&gt;-&amp;gt; &lt;strong&gt;HomeController&lt;/strong&gt; [GetMapping]에서 return index.jsp&lt;/li&gt;
          &lt;li&gt;6번으로 넘어가지 않는다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;인증 절차 실패:
        &lt;ul&gt;
          &lt;li&gt;request parameter에 error 추가&lt;/li&gt;
          &lt;li&gt;return redirect:/login?error; [GET]&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;LoginController&lt;/strong&gt; login method [GetMapping] 실행
    &lt;ul&gt;
      &lt;li&gt;error request parameter 유무 체크&lt;/li&gt;
      &lt;li&gt;Model에 errorMsg 저장&lt;/li&gt;
      &lt;li&gt;return login.jsp&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;login.jsp에서 errorMsg 표시&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;span style=&quot;background-color: #e1e1e1&quot;&gt;&lt;strong&gt;로그아웃 인증 성공&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;home.jsp에서 LOGOUT을 Submit [POST]
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;form id=&quot;logout&quot; action=&quot;&amp;lt;c:url value=&quot;/logout&quot; /&amp;gt;&quot; method=&quot;post&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;참고) 이때, value 값은 &lt;strong&gt;&lt;em&gt;개발자가 임의로 정할 수 없다.&lt;/em&gt;&lt;/strong&gt; (spring security에 지정되어 있는 이름)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Spring Security&lt;/strong&gt; logout method [PostMapping] 실행
    &lt;ul&gt;
      &lt;li&gt;로그아웃 성공:
        &lt;ul&gt;
          &lt;li&gt;request parameter에 logout 추가&lt;/li&gt;
          &lt;li&gt;return redirect:/login?lougut; [GET]&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;LoginController&lt;/strong&gt; login method [GetMapping] 실행
    &lt;ul&gt;
      &lt;li&gt;logout request parameter 유무 체크&lt;/li&gt;
      &lt;li&gt;model에 logoutSuccessMsg 저장&lt;/li&gt;
      &lt;li&gt;return login.jsp&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;login.jsp에서 logoutSuccessMsg 표시&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;MVC Architecture에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/11/05/mvc-architecture.html&quot;&gt;MVC Architecture 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;Web Application Structure와 web.xml의 역할에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/10/29/web-application-structure.html&quot;&gt;Web Application Structure 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-security/site/docs/current/guides/html5/helloworld-xml.html&quot;&gt;https://docs.spring.io/spring-security/site/docs/current/guides/html5/helloworld-xml.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-security/site/docs/current/guides/html5/form-javaconfig.html&quot;&gt;https://docs.spring.io/spring-security/site/docs/current/guides/html5/form-javaconfig.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/spring-security-login&quot;&gt;https://www.baeldung.com/spring-security-login&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-security/blob/ec970c9b8e7c2d669bc80b1bd21ad3ba91a20461/samples/xml/servletapi/src/main/java/org/springframework/security/samples/servletapi/mvc/ServletApiController.java&quot;&gt;https://github.com/spring-projects/spring-security/blob/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-security/site/docs/4.0.x/reference/html/appendix-schema.html&quot;&gt;schema 참고&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://hydrasky.com/network-security/cross-site-request-forgery-csrf/&quot;&gt;CSRF attack&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Thu, 03 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/03/spring-security.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/03/spring-security.html</guid>
        
        <category>spring</category>
        
        <category>web</category>
        
        <category>spring-security</category>
        
        <category>security</category>
        
        
      </item>
    
      <item>
        <title>[SpringMVC] Spring MVC WebForm</title>
        <description>&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Request Paremeter의 종류&lt;/li&gt;
    &lt;li&gt;Data Binding&lt;/li&gt;
    &lt;li&gt;Data Validation&lt;/li&gt;
    &lt;li&gt;Data Buffering&lt;/li&gt;
    &lt;li&gt;Error Message&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/spring-framework/springwebform-overview.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;request-parameter의-종류&quot;&gt;Request Parameter의 종류&lt;/h2&gt;
&lt;p&gt;Request Parameter는 HTTP Request Message 안에 담겨서 보내진다.
&lt;img src=&quot;/images/spring-framework/springwebform-requestparam.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Request Parameter는 2가지 방식으로 전달된다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-get-방식--query-string&quot;&gt;1. GET 방식 : Query String&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;url 뒤에 query string 형식으로 붙어서 보내진다.&lt;/li&gt;
  &lt;li&gt;Ex) 조회와 같이 DB를 변경하지 않는 작업에 이 방식을 사용한다.
&lt;img src=&quot;/images/spring-framework/springwebform-requestparam-get.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-post-방식--http-entity-body&quot;&gt;2. POST 방식 : HTTP Entity Body&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP Request Message의 Body에 담겨서 보내진다.&lt;/li&gt;
  &lt;li&gt;Ex) 암호화, 회원가입(password) 등 주로 DB를 변경하는 작업에 이 방식을 사용한다.
&lt;img src=&quot;/images/spring-framework/springwebform-requestparam-post.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;data-binding&quot;&gt;Data Binding&lt;/h2&gt;
&lt;p&gt;request parameters가 form bean(=command object)에 바인딩되는 것을 말한다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;예시 
&lt;img src=&quot;/images/spring-framework/springwebform-databinding.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-naive-solution-requestparam-어노테이션&quot;&gt;1. Naive Solution (@RequestParam 어노테이션)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;@RequestParam 어노테이션 이용
    &lt;ul&gt;
      &lt;li&gt;method 인자에 request parameter을 binding 해준다.&lt;/li&gt;
      &lt;li&gt;반드시 query string의 key 이름이 동일해야 값을 가져올 수 있다.&lt;/li&gt;
      &lt;li&gt;method 인자에 form bean을 선언하지 않는다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&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;@RequestMapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/docreate&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@RequestParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&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;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;nd&quot;&gt;@RequestParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;email&quot;&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;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&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;// we manually populate the Offer object with &lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;// the data coming from the user&lt;/span&gt;
   &lt;span class=&quot;nc&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offer&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;Offer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

   &lt;span class=&quot;n&quot;&gt;offer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;offer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setEmail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ul&gt;
      &lt;li&gt;method 인자가 3개 이상이면 2번째 방법을 이용한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-spring-data-binding-자동-binding&quot;&gt;2. Spring Data Binding (자동 Binding)&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;method 인자에 form bean을 선언한다.
    &lt;ul&gt;
      &lt;li&gt;Spring이 자동으로 request paraters를 객체에 binding 해준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&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;@RequestMapping&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/docreate&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RequestMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offer&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;// offer object will be automatically populated &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// with request parameters&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;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Binding 과정&lt;/strong&gt;
&lt;img src=&quot;/images/spring-framework/springwebform-databinding-process.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;form bean 객체(Offer 객체)를 생성한다.&lt;/li&gt;
  &lt;li&gt;request parameter으로부터 form bean에 내용이 자동으로 binding된다.
    &lt;ul&gt;
      &lt;li&gt;이때, form bean(POJO)에 setter method가 구현되어 있어야 binding이 가능하다.&lt;/li&gt;
      &lt;li&gt;또한 controller의 method 인자에 form bean을 선언되어 있어야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;controller에서 form bean을 자동으로 model에 넣어준다. (form bean은 model attribute이다.)&lt;/li&gt;
  &lt;li&gt;model을 view에 넘겨준다.
    &lt;ul&gt;
      &lt;li&gt;controller에서 form bean을 model에 넣어 view에 전달한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;view는 form bean 내용에 접근할 수 있고 이 내용을 rendering 할 수 있다.
    &lt;ul&gt;
      &lt;li&gt;즉, controller로부터 전달받은 model에 있는 form bean(Offer 객체, model attribute)를 사용하여 request parameter에 접근할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-html 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;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt; 
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Thanks&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt; 
    Hi, ${offer.name}.&lt;span class=&quot;nt&quot;&gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
    You have successfully registered.
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;data-validation&quot;&gt;Data Validation&lt;/h2&gt;
&lt;p&gt;사용자가 실수로 잘못된 정보를 입력했을 때 잘못된 양식임을 알려주기 위해 사용한다.&lt;/p&gt;

&lt;h3 id=&quot;1-hibernate-validator&quot;&gt;1. Hibernate Validator&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;사용자의 오류를 감지하기 위해 form bean에 캡슐화된 form data의 유효성을 검사해야 한다.&lt;/li&gt;
  &lt;li&gt;Bean Validation API(JSR-303)는 JavaBean 유효성 검사를 위한 API를 정의하는 명세서이다.
    &lt;ul&gt;
      &lt;li&gt;이 명세의 구현체가 Hibernate Validator(라이브러리)이다.&lt;/li&gt;
      &lt;li&gt;검증 제약 조건을 bean properties에 어노테이션을 달아 설정할 수 있다.&lt;/li&gt;
      &lt;li&gt;Ex) @NotNull, &lt;a href=&quot;http://www.rubular.com/&quot;&gt;@Pattern&lt;/a&gt;, @Size, @Email 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;pom.xml에 추가&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.hibernate&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;hibernate-validator&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;5.2.4.Final&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dependency&amp;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-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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Pattern&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regexp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^[A-Z]{1}[a-z]+$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 정규표현(Regular Expression)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotEmpty&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Email&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;h3 id=&quot;2-message-interpolation&quot;&gt;2. Message Interpolation&lt;/h3&gt;
&lt;p&gt;메시지 보간법(삽입 어구)은 위배된 Bean 유효성 검증 제약 조건에 대한 오류 메시지를 생성하는 것이다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;메시지 속성을 통해 각 속성의 message descriptor를 정의할 수 있다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;예시&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&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;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

   &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;nd&quot;&gt;@Size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Name must be between 3 and 100 characters&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;nd&quot;&gt;@Email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;please provide a valid email address&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;nd&quot;&gt;@NotEmpty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;the email address cannot be empty&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;nd&quot;&gt;@Size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Text must be between 5 and 100 characters&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&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;ul&gt;
  &lt;li&gt;문제점
    &lt;ul&gt;
      &lt;li&gt;message resources(불변)가 code 안에 들어가 있는 형태이므로 별도의 파일로 관리하는 것이 바람직하다.&lt;/li&gt;
      &lt;li&gt;사용자의 location(지역)에 맞는 언어로 바꿔줘야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-validating-object&quot;&gt;3. Validating Object&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;@Valid 어노테이션
    &lt;ul&gt;
      &lt;li&gt;@Valid 어노테이션을 통해 Hibernate가 자동으로 유효성 검사를 한다.&lt;/li&gt;
      &lt;li&gt;controller method의 인자 중 검증할 객체 인자 앞에 해당 어노테이션을 단다.&lt;/li&gt;
      &lt;li&gt;@Valid 어노테이션은 객체의 유효성을 먼저 확인한 다음 모델에 객체를 추가한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;BindingResult Object
    &lt;ul&gt;
      &lt;li&gt;유효성 검사 과정의 결과를 나타낸다.&lt;/li&gt;
      &lt;li&gt;필요한 경우에 controller method의 인자에 추가한다.&lt;/li&gt;
      &lt;li&gt;form bean과 같이 model에 들어가서 View에 넘겨준다.&lt;/li&gt;
      &lt;li&gt;이를 통해 View는 error message를 출력할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;즉, @Valid에 의해 Spring이 자동으로 유효성을 검사하고, 그 결과인 BindingResult 객체를 자동으로 Model에 넣어준다.
    &lt;ul&gt;
      &lt;li&gt;form bean과 BindingResult가 포함된 Model을 View에서 사용할 수 있다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;예시&lt;/li&gt;
&lt;/ul&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;@RequestMapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Valid&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Offer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BindingResult&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;o&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;if&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;na&quot;&gt;hasErrors&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;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ObjectError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;errors&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;na&quot;&gt;getAllErrors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

       &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ObjectError&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;error:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errors&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;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDefaultMessage&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;createoffer&quot;&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;o&quot;&gt;...&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;hr /&gt;

&lt;h2 id=&quot;data-buffering&quot;&gt;Data Buffering&lt;/h2&gt;
&lt;p&gt;사용자가 잘못된 정보를 입력했을 때 처음부터 다시 입력할 필요가 없도록 입력한 정보를 view에 그대로 남아있게 해주는 것이다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;예시 
&lt;img src=&quot;/images/spring-framework/springwebform-databuffering.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-spring-form-tag-library&quot;&gt;1. Spring Form Tag Library&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;사용자의 입력 내용을 web form에 바인딩해야 한다.
    &lt;ul&gt;
      &lt;li&gt;Spring은 data binding-aware tags 세트를 제공한다.&lt;/li&gt;
      &lt;li&gt;즉, 알아서 사용자가 입력했던 내용을 매칭해서 그려준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;‘spring form tag library’의 태그를 사용하려면 JSP 페이지의 맨 위에 다음 지시문을 추가해야 한다.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;%@ taglib prefix=&quot;sf&quot; uri=&quot;http://www.springframework.org/tags/form&quot;%&amp;gt;&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;prefix=”sf”: 내가 원하는 약어 설정&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Spring form tag lib&lt;/td&gt;
      &lt;td&gt;HTML&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sf:form&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&amp;lt;form&amp;gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sf:input&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&amp;lt;input  type=”text”&amp;gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sf:password&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&amp;lt;input  type=”password”&amp;gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sf:checkbox&amp;gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&amp;lt;input  type=”checkbox”&amp;gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;2-revised-jsp-and-error-message&quot;&gt;2. Revised JSP and Error Message&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/spring-framework/springwebform-revised.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;‘spring form tag library’ 태그 사용 지시문 선언&lt;/li&gt;
  &lt;li&gt;‘spring form tag’ 사용&lt;/li&gt;
  &lt;li&gt;‘spring form tag’ 사용
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sf:errors&amp;gt;&lt;/code&gt; 태그는 유효성 검사 후 BindingResult 객체로부터 받은 error message를 HTML에 랜더링한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Model에 들어 있는 model attribute의 이름
    &lt;ul&gt;
      &lt;li&gt;빈 객체로 넘어온 offer이라는 이름의 model attribute(Offer 객체)에 사용자가 입력한 데이터를 넣기 위한 설정&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;name=”name” -&amp;gt; path=”name”으로 사용
    &lt;ul&gt;
      &lt;li&gt;Offer 객체의 어떤 속성과 binding 할지를 명시&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;전체-과정&quot;&gt;전체 과정&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/spring-framework/springwebform-total.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;MVC Architecture에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/11/05/mvc-architecture.html&quot;&gt;MVC Architecture 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
  &lt;li&gt;Web Application Structure와 web.xml의 역할에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/10/29/web-application-structure.html&quot;&gt;Web Application Structure 이해하기&lt;/a&gt;를 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- # References
&gt; - []() --&gt;
</description>
        <pubDate>Wed, 02 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/02/spring-mvc-webform.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/02/spring-mvc-webform.html</guid>
        
        <category>spring</category>
        
        <category>springMVC</category>
        
        <category>mvc</category>
        
        <category>web</category>
        
        <category>webform</category>
        
        <category>data-binding</category>
        
        <category>data-validation</category>
        
        
      </item>
    
      <item>
        <title>[Spring] Spring UTF8 한글 설정하기</title>
        <description>&lt;h2 id=&quot;오류-내용&quot;&gt;오류 내용&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spring 프로젝트에서 한글이 깨짐&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;한글이 깨지는 이유
    &lt;ul&gt;
      &lt;li&gt;보통 브라우저 —&amp;gt; 서버 —&amp;gt; DBMS 로 같은 내용의 한글이 서비스 처리를 하는 단계에서 매번 다른 문자코드를 사용하여 재표현되기 때문이다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;한글을 올바르게 표현하는 방법
    &lt;ul&gt;
      &lt;li&gt;GET와 POST 방식이 다르다.&lt;/li&gt;
      &lt;li&gt;GET
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;3 이용&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;데이터가 GET방식에서는 요청정보 Header의 URI에 포함되어 전달된다.&lt;/li&gt;
          &lt;li&gt;서블릿의 영역 밖에 존재한다.&lt;/li&gt;
          &lt;li&gt;URI에 대해 인코딩 처리 작업&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;POST
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;1 + 2 이용&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;데이터가 POST방식에서는 요청정보 Body에 포함되어 전달된다.&lt;/li&gt;
          &lt;li&gt;서블릿에서 어느 정도 컨트롤이 가능하다.
&lt;!-- * 요청정보를 받는 페이지에서 인코딩 처리 --&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;해결-방법&quot;&gt;해결 방법&lt;/h2&gt;
&lt;h3 id=&quot;1-post-방식-스프링-웹-프로젝트-webxml에-utf-8-설정&quot;&gt;1. [POST 방식] 스프링 웹 프로젝트 &lt;strong&gt;web.xml&lt;/strong&gt;에 utf-8 설정&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;filter&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;encodingFilter&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-class&amp;gt;&lt;/span&gt;org.springframework.web.filter.CharacterEncodingFilter&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-class&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;init-param&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-name&amp;gt;&lt;/span&gt;encoding&lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-name&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-value&amp;gt;&lt;/span&gt;UTF-8&lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-value&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/init-param&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;init-param&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-name&amp;gt;&lt;/span&gt;forceEncoding&lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-name&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;nt&quot;&gt;&amp;lt;param-value&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/param-value&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/init-param&amp;gt;&lt;/span&gt; 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt; 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-mapping&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;filter-name&amp;gt;&lt;/span&gt;encodingFilter&lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-name&amp;gt;&lt;/span&gt; 
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;url-pattern&amp;gt;&lt;/span&gt;/*&lt;span class=&quot;nt&quot;&gt;&amp;lt;/url-pattern&amp;gt;&lt;/span&gt; 
 &lt;span class=&quot;nt&quot;&gt;&amp;lt;/filter-mapping&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;!-- * ![Filter 과정 그림]() // 나중에 추가 --&gt;
&lt;ul&gt;
  &lt;li&gt;Spring Web Project - &lt;strong&gt;POST 방식&lt;/strong&gt;에서의 한글 깨짐 해결 방법&lt;/li&gt;
  &lt;li&gt;역할
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;브라우저 —&amp;gt; 요청정보 Body 데이터 —UTF8 인코딩—&amp;gt; Java 단에서의 데이터 처리&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;CharacterEncodingFilter
        &lt;ul&gt;
          &lt;li&gt;HTTP상에서 주고 받는 데이터의 헤더값을 UTF-8로 인코딩&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Servlet에서의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request.setCharacterEncoding(&quot;utf-8&quot;);&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;POST로 인코딩 데이터를 받는 Servlet에서의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request.setCharacterEncoding(&quot;utf-8&quot;);&lt;/code&gt; 처리와 동일한 기능을 수행한다.&lt;/li&gt;
          &lt;li&gt;즉, 이 Filter를 설정하면 POST 요청을 보내는(Submit) 모든 Controller(Servlet) 마다 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request.setCharacterEncoding(&quot;utf-8&quot;);&lt;/code&gt; 내용을 추가하지 않아도 된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;또한 DB에서 불러올 한글 데이터들의 한글 깨짐 현상을 해결한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;사용
    &lt;ul&gt;
      &lt;li&gt;해당 filter를 매핑할 때 모든 URL에 대해 인코딩될 수 있도록 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/*&lt;/code&gt;와 같이 url-pattern을 설정한다.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;주의!)&lt;/strong&gt; Spring Security 설정이 있는 경우,&lt;br /&gt; 한글 필터 설정이 springSecurityFilterChain 앞에 위치해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-post-방식-jsp-파일에-utf-8-설정&quot;&gt;2. [POST 방식] &lt;strong&gt;.jsp 파일&lt;/strong&gt;에 utf-8 설정&lt;/h3&gt;
&lt;div class=&quot;language-jsp 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;nt&quot;&gt;&amp;lt;%@ page &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;contentType=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html; charset=UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt; pageEncoding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt; language=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;java&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Spring Web Project - &lt;strong&gt;POST 방식&lt;/strong&gt;에서의 한글 깨짐 해결 방법&lt;/li&gt;
  &lt;li&gt;역할
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;응답정보 Body 데이터(JSP 내의 Java 코드 + HTML) —UTF8 인코딩—&amp;gt; 브라우저&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;JSP의 인코딩 방식이 무엇인지 알 수 있게 선언하는 것&lt;/li&gt;
          &lt;li&gt;jsp 파일에서의 한글 깨짐이 해결된다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Servlet에서의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;response.setContentType(&quot;text/html;charset=UTF-8&quot;);&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;Servlet에서의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;response.setContentType(&quot;text/html;charset=UTF-8&quot;);&lt;/code&gt; 처리와 유사한 기능을 수행한다.&lt;/li&gt;
          &lt;li&gt;Servlet/JSP 단에서의 설정 방벙의 차이점은&lt;br /&gt; 아래의 &lt;strong&gt;참고2)&lt;/strong&gt; &lt;em&gt;dispatcher-servlet.xml에서의 설정과 차이점&lt;/em&gt;을 참고하자.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;참고1)&lt;/strong&gt; &lt;a href=&quot;https://okky.kr/article/284291&quot;&gt;왜 UTF-8 이 두 번 선언이 되어 있을까&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;contentType: 서버에서 생성될 HTML의 charset에 대한 정보&lt;/li&gt;
      &lt;li&gt;pageEncoding: JSP 내의 Java 코드에 대한 charset에 대한 정보&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;참고2)&lt;/strong&gt; &lt;a href=&quot;https://okky.kr/article/284291&quot;&gt;dispatcher-servlet.xml에서의 설정과 차이점&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-xml 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;c&quot;&gt;&amp;lt;!-- dispatcher-servlet.xml에서의 설정 (Servlet/JSP 단에서의 설정) 예시 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;bean&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;prefix&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/WEB-INF/views/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;suffix&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.jsp&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;property&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;contentType&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html; charset=UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;Servlet/JSP 단에서의 설정
      &lt;ul&gt;
        &lt;li&gt;dispatcher-servlet.xml에서의 설정은 &lt;em&gt;Servlet 단&lt;/em&gt;에서의 설정을 의미한다.&lt;/li&gt;
        &lt;li&gt;.jsp 파일 상의 page 설정은 &lt;em&gt;JSP 단&lt;/em&gt;에서의 설정을 의미한다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;Servlet/JSP 단에서의 설정 방법의 차이
      &lt;ul&gt;
        &lt;li&gt;JSP 디폴트 contentType: ISO-8859-1&lt;/li&gt;
        &lt;li&gt;아무리 Servlet에서 response.setContentType 결정해서 보내더라도 .jsp page 자체의 contentType은 jsp spec에서 결정되므로 직접 기술해주지 않으면 ISO-8859-1로 설정된다.&lt;/li&gt;
        &lt;li&gt;Servlet 단에서의 설정은 JSP가 아닌 텍스트 리턴 시에만 이용된다.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;따라서, &lt;strong&gt;직접 .jsp page에 기술하는 것이 좋다.&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;post-방식에서의-한글-처리-추가-설명-servlet에서-한글처리&quot;&gt;POST 방식에서의 한글 처리 추가 설명 (Servlet에서 한글처리)&lt;/h3&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;@WebServlet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/loginServlet&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoginServlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpServlet&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;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doPost&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;HttpServletRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpServletResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* 요청정보 Body에 있는 문자열들을 인자값으로 지정한 문자코드로 인코딩한다. */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCharacterEncoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;//getParameter는 중복되지 않고 유일하게 하나만 넘어올 떄 사용된다.&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;username&quot;&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;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;cm&quot;&gt;/* 응답정보 문자열들을 인자값으로 지정한 문자코드로 인코딩한다.  */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setContentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html;charset=UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;PrintWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getWriter&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;n&quot;&gt;htmlResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;html&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;htmlResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Query 문자열 한글 테스트&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;htmlResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;h2&amp;gt; your name is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;br/&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;htmlResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;h2&amp;gt; your password is &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;br/&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htmlResponse&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;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;request.setCharacterEncoding() 메서드 역할
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;브라우저 —&amp;gt; 요청정보 Body 데이터 —UTF8 인코딩—&amp;gt; Java 단에서의 데이터 처리&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;1번 [POST 방식] 스프링 웹 프로젝트 web.xml에 utf-8 설정 과정에 해당한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;한글 처리를 해주는 메서드는 HttpServletRequest의 상위 객체인 ServletRequest에서 제공하는 setCharacterEncoding() 메서드이다.&lt;/li&gt;
      &lt;li&gt;setCharacterEncoding(“UTF-8”) 메서드는 클라이언트가 전달한 요청정보 Body에 있는 데이터(문자열)들을 메서드 인자값으로 지정한 문자코드(UTF-8)로 인코딩해준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;request.setCharacterEncoding() 메서드 사용
    &lt;ul&gt;
      &lt;li&gt;Java 단에서 데이터를 받아오기 전((getParameter() 메서드)에 인코딩을 처리한다.&lt;/li&gt;
      &lt;li&gt;즉, getParameter() 메서드 위에서 사용해야 한다.
        &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;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCharacterEncoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;param&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;response.setContentType() 메서드 역할
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;응답정보 Body 데이터(Text 데이터) —UTF8 인코딩—&amp;gt; 브라우저&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;2번 [POST 방식] .jsp 파일에 utf-8 설정 과정에 해당한다.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;response.setContentType(“text/html;charset=UTF-8”) 메서드는 클라이언트에 전달할 응답정보 Body에 있는 데이터(문자열)들을 메서드 인자값으로 지정한 문자코드(UTF-8)로 인코딩해준다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;response.setContentType() 메서드 사용
    &lt;ul&gt;
      &lt;li&gt;html을 출력하는 메서드 위에서 사용해야 한다.
        &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;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setContentType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html;charset=UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;PrintWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getWriter&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;n&quot;&gt;htmlResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;한글 테스트&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;/html&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;htmlResponse&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;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-get-방식-tomcat-서버의-환경-설정-파일-serverxml에-utf-8-설정&quot;&gt;3. [GET 방식] Tomcat 서버의 환경 설정 파일 &lt;strong&gt;server.xml&lt;/strong&gt;에 utf-8 설정&lt;/h3&gt;
&lt;div class=&quot;language-xml 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;nt&quot;&gt;&amp;lt;Connector&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;connectionTimeout=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20000&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;8080&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HTTP/1.1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;redirectPort=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;8443&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;URIEncoding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;Connector&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;8009&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AJP/1.3&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;redirectPort=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;8443&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;URIEncoding=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Web Project - &lt;strong&gt;GET 방식&lt;/strong&gt;에서의 한글 깨짐 해결 방법
    &lt;ul&gt;
      &lt;li&gt;GET 방식으로 전달된 질의 문자열들은 URI에 포함되어 전달되기 때문에 URI에 대해 인코딩 처리 작업을 해야한다.&lt;/li&gt;
      &lt;li&gt;서버마다 기본적으로 URI 인코딩 문자코드가 정해져 있으며 톰캣8 버전에서는 UTF-8 문자코드가 기본값으로 적용된다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Servers(아파치 톰캣)의 해당 프로젝트 config 폴더 &amp;gt; server.xml 파일 &amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URIEncoding=&quot;UTF-8&quot;&lt;/code&gt; property를 추가한다.
    &lt;ul&gt;
      &lt;li&gt;서버에서 직접 URI를 UTF-8로 인코딩하는 과정&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;4-html-파일에-utf-8-설정&quot;&gt;4. &lt;strong&gt;.html 파일&lt;/strong&gt;에 utf-8 설정&lt;/h3&gt;
&lt;div class=&quot;language-html 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;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;http-equiv=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html; charset=UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Home&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;head 태그 영역을 위와 같이 설정한다.
    &lt;ul&gt;
      &lt;li&gt;최신 IDE(통합 개발 환경)를 사용한다면 기본적인 인코딩 방식은 UTF-8로 설정이 되어있다.&lt;/li&gt;
      &lt;li&gt;하지만 Windows 운영체제는 기본 인코딩 값으로 여전히 euc-kr방식을 사용하기 때문에, 해당 페이지의 인코딩 방식(utf-8)이 무엇인지 브라우저가 알 수 있게 선언해야 한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;사용
    &lt;ul&gt;
      &lt;li&gt;HTML5의 경우
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;&lt;/code&gt;를 head 태그 안에 삽입&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;XHTML의 경우
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;&lt;/code&gt;를 head 태그 안에 삽입&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;관련된-post&quot;&gt;관련된 Post&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;Servlet과 JSP의 차이에 대해 알고 싶으시면 &lt;a href=&quot;https://gmlwjd9405.github.io/2018/11/04/servlet-vs-jsp.html&quot;&gt;Servlet과 JSP의 차이&lt;/a&gt;을 참고하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;
&lt;blockquote&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/seungjin-shin/Treeze/issues/1ㅏ&quot;&gt;https://github.com/seungjin-shin/Treeze/issues/1&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://jijs.tistory.com/entry/Spring-Framework-에서-UTF8-한글-설정&quot;&gt;http://jijs.tistory.com/entry/Spring-Framework-에서-UTF8-한글-설정&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://blog.hanumoka.net/2018/04/18/spring-20180418-spring-set-korean/&quot;&gt;https://blog.hanumoka.net/2018/04/18/spring-20180418-spring-set-korean/&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://egloos.zum.com/springmvc/v/513986&quot;&gt;http://egloos.zum.com/springmvc/v/513986&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://ofcourse.kr/html-course/%EC%9D%B8%EC%BD%94%EB%94%A9&quot;&gt;https://ofcourse.kr/html-course/%EC%9D%B8%EC%BD%94%EB%94%A9&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://okky.kr/article/194808&quot;&gt;인코딩 중복&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://opentutorials.org/module/3569/21229&quot;&gt;POST/GET에 따라 다른 한글 깨짐 처리 방법&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://okky.kr/article/197156&quot;&gt;Servlet/JSP에서의 response.setContentType&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://gmlwjd9405.github.io/2019/01/01/spring-utf8.html</link>
        <guid isPermaLink="true">http://gmlwjd9405.github.io/2019/01/01/spring-utf8.html</guid>
        
        <category>error</category>
        
        <category>spring</category>
        
        <category>utf8</category>
        
        <category>한글깨짐</category>
        
        <category>encoding</category>
        
        
      </item>
    
  </channel>
</rss>
