<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Moon.log</title>
        <link>https://velog.io/</link>
        <description>매일 성장하는 개발자 되기😊</description>
        <lastBuildDate>Mon, 05 Jun 2023 14:04:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Moon.log</title>
            <url>https://images.velog.io/images/k_moonj/profile/08babea9-dc21-4fa0-8860-460bc7066e69/미모티콘.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Moon.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/k_moonj" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[TIL] 230605]]></title>
            <link>https://velog.io/@k_moonj/TIL-230603</link>
            <guid>https://velog.io/@k_moonj/TIL-230603</guid>
            <pubDate>Mon, 05 Jun 2023 14:04:03 GMT</pubDate>
            <description><![CDATA[<ul>
<li>Maven프로젝트를 만들어 패키지 실행시 <code>Source option 5 is no longer supported. Use 6 or later</code>이라는 오류가 떴다. </li>
</ul>
<p>구글링을 하다가 pom.xml에 </p>
<pre><code class="language-xml">    &lt;properties&gt;
        &lt;maven.compiler.source&gt;11&lt;/maven.compiler.source&gt;
        &lt;maven.compiler.target&gt;11&lt;/maven.compiler.target&gt;
    &lt;/properties&gt;</code></pre>
<p>를 추가해줘야 한다고 해서 찾아보니 </p>
<ul>
<li>Maven은 따로 설정하지 않으면 default로 자바 default버전으로 1.5를 사용한다고 한다. (xml을 덮어쓰기하느라 초기에 생성된 xml파일을 제대로 보지 않았는데 다시 보니 원래 properties에 compiler 관련 내용이 있었다. </li>
</ul>
<hr>
<h3 id="빌드관리도구---gradle-vs-maven">빌드관리도구 - Gradle vs Maven</h3>
<img src="https://velog.velcdn.com/images/k_moonj/post/bb04d9ec-a7fd-4649-9587-92a111c58b4c/image.JPG">



<h4 id="gradle">Gradle</h4>
<ul>
<li>JVM 기반, 오픈소스 기반의 빌드 자동화 도구 </li>
<li>Groovy기반 DSL로 작성</li>
</ul>
<h4 id="maven">Maven</h4>
<ul>
<li>아파치 Ant의 대안으로 만들어짐 </li>
<li>라이브러리와 연관된 라이브러리들까지 연동되서 관리됨</li>
</ul>
<blockquote>
</blockquote>
<p>✅ <strong>pom.xml</strong>
POM (Project Object Model)을 설정하는 부분으로 Maven의 빌드 정보를 담고있으며 프로젝트의 빌드 옵션을 설정한다. </p>
<p><code>&lt;properties&gt;</code> : 프로젝트 관련 속성 
<code>&lt;dependencies&gt;</code> : 프로젝트가 의존하는 라이브러리들 정보 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 푸드 파이트 대회]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%ED%91%B8%EB%93%9C-%ED%8C%8C%EC%9D%B4%ED%8A%B8-%EB%8C%80%ED%9A%8C</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%ED%91%B8%EB%93%9C-%ED%8C%8C%EC%9D%B4%ED%8A%B8-%EB%8C%80%ED%9A%8C</guid>
            <pubDate>Wed, 16 Nov 2022 10:25:03 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
</blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/134240">Level1 : 푸드 파이트 대회</a></p>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/b1df7ec5-06d4-4a49-9bb2-9cfea4921145/image.JPG" alt=""></p>
<hr>
<h3 id="💡-풀이">💡 풀이</h3>
<ul>
<li>StringBuilder로 <code>음식 개수 / 2</code> 만큼 배치해준다. </li>
<li>물(&#39;0&#39;)을 기준으로 음식이 대칭되기 때문에 <code>reverse()</code>를 이용해 붙여줬다. </li>
</ul>
<pre><code class="language-java">class Solution {
    public String solution(int[] food) {

        StringBuilder sb = new StringBuilder();

        // food[0] : 물 
        for(int i = 1; i &lt; food.length; i++) {
            int division = food[i] / 2;

            for(int j = 0; j &lt; division; j++) {
                sb.append(i);
            }
        }
        String answer = sb.toString() + &quot;0&quot; + sb.reverse().toString();
        return answer;
    }
}</code></pre>
<p>나는 문자열을 뒤집어야 한다는 생각만 하느라 <code>reverse()</code> 메서드를 쓰기 위해 StringBuilder를 사용했지만 String으로도 가능하다. 이 방법도 알아둬야 할 것 같다. (연산이 자주 발생하면 시간초과 문제 때문에 StringBuilder를 사용해야 하는 경우가 많다.) </p>
<pre><code class="language-java">String answer = &quot;0&quot;;

for(int i = food.length - 1; i &gt; 0; i--) {
    for(int j = 0; j &lt; food[i] / 2; j++) {
        answer = i + answer + i;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 최소직사각형]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%B5%9C%EC%86%8C%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%B5%9C%EC%86%8C%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</guid>
            <pubDate>Sat, 05 Nov 2022 06:51:41 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/86491">Level1 : 최소직사각형</a></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/6fd6d4ab-e7ff-4d2f-88b5-32e2e09d8f54/image.JPG" alt=""></p>
<hr>
<h3 id="💡풀이">💡풀이</h3>
<p>완전탐색 문제이다. 
명함을 수납할 수 있는 가장 작은 지갑의 크기를 구해야 한다. <code>가로</code>와 <code>세로</code>가 주어지는데 문제 설명에서 주어진 예시처럼 30*70인 명함을 가로로 눕히면 가로가 70, 세로가 30이 되기 때문에 가장 긴 세로 길이가 50이 된다. 가장 긴 가로 길이는 80, 세로 길이는 50이 되므로 조건에 맞는 가장 작은 지갑 사이즈는 4000이다.</p>
<ul>
<li>처음에는 가로와 세로를 바꿀 수 있기 때문에 <code>가로</code>와 <code>세로</code> 중 큰 값과 작은 값을 한 쪽으로 몰아 설정해줄 수 있다. <code>Math.max(가로, 세로)</code>와 <code>Math.min(가로,세로)</code>를 사용해 둘 중에 큰 값을 가로, 작은 값을 세로로 설정했다.</li>
</ul>
<pre><code class="language-java">class Solution {
    public int solution(int[][] sizes) {
        int answer = 0;

        // 가로는 긴거 세로는 짧은 거로 설정해주기 (하나에 몰아주기) 
        int max_w = 0; 
        int max_h = 0;

        for(int i = 0; i &lt; sizes.length; i++) {
            int w = Math.max(sizes[i][0], sizes[i][1]);
            int h = Math.min(sizes[i][0], sizes[i][1]);
            max_w = Math.max(max_w, v);
            max_h = Math.max(max_h, h);
        }
        answer = max_w * max_h;
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 시저 암호]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%8B%9C%EC%A0%80-%EC%95%94%ED%98%B8</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%8B%9C%EC%A0%80-%EC%95%94%ED%98%B8</guid>
            <pubDate>Mon, 31 Oct 2022 08:24:17 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
</blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12926">Level.1 : 시저 암호</a></p>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/902530a5-542b-4cdf-8cae-80ea92cd34df/image.JPG" alt=""></p>
<hr>
<h3 id="💡-풀이">💡 풀이</h3>
<ul>
<li><p><code>알파벳</code> , <code>문자열의 거리</code> 라는 키워드를 보면 바로 <code>아스키코드</code>를 떠올릴 수 있을 것이다. </p>
<blockquote>
</blockquote>
<ul>
<li>A(65) ~ Z(90)</li>
<li>a(97) ~ z(122) </li>
</ul>
</li>
</ul>
<p> 문제에 주어진 예시처럼 z를 4만큼 밀게되면 <code>z -&gt; a -&gt; b -&gt; c -&gt; d</code>이기 때문에 d가 된다. z는 122이고 d는 100인데 알파벳이 26글자이기 때문에 <code>122-26+4</code>를 해서 </p>
<pre><code class="language-java">class Solution {
    public String solution(String s, int n) {
        String answer = &quot;&quot;;
        for(int i = 0; i &lt; s.length(); i++) {
            char ch = s.charAt(i);
            if(ch == &#39; &#39;) {
                answer += ch;
                continue;
            }
            if(ch &gt;= &#39;a&#39; &amp;&amp; ch &lt;= &#39;z&#39;) {
                if(ch + n &gt; &#39;z&#39;) {
                    answer += (char)(ch - 26 + n);
                } else {
                    answer += (char)(ch + n);
                }
            } else if(ch &gt;= &#39;A&#39; &amp;&amp; ch &lt;= &#39;Z&#39;) {
                if(ch + n &gt; &#39;Z&#39;) {
                    answer += (char)(ch - 26 + n);
                } else {
                    answer += (char)(ch + n);
                }
            }
        }
        return answer;
    }
}</code></pre>
<p>사실 대/소문자에 상관없이 해줘야하는 연산이 같기 때문에 조건문을 일일이 써주는 게 맞는지에 대한 고민을 계속 했다. </p>
<pre><code class="language-java">(char)(ch - 26 +n) 과 (char)(ch + n) </code></pre>
<p>다른 사람들의 풀이를 보고나서야 <code>isUpperCase()</code> 와 <code>isLowerCase()</code>가 떠올랐다.</p>
<pre><code class="language-java"></code></pre>
<hr>
<h3 id="💬-추가-내용">💬 추가 내용</h3>
<ul>
<li><p>시저암호가 진짜 존재하는 건지 궁금해서 찾아보니 정말 존재하는 암호화 방식이었다. </p>
<p>사실 이 문제의 이름인 <code>시저 암호</code>는 <code>카이사르 암호</code>라고도 부르는 고대 암호로 문제의 내용대로 key값을 받아 해당 숫자만큼 평문을 쉬프트해주는 치환암호이다. 쉽게 사용할 수 있는 대신 철자의 빈도와 자주 사용되는 단어, 형태를 이용해서 쉽게 풀린다는 단점이 있다고 한다. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 수박수박수박수박수박수?]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98%EB%B0%95%EC%88%98</guid>
            <pubDate>Mon, 26 Sep 2022 14:23:01 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
</blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12922">Level1 : 수박수박수박수박수박수?</a></p>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/23da852c-d638-4d6e-9f85-3ba0232854dc/image.JPG" alt=""></p>
<hr>
<h3 id="💡-풀이">💡 풀이</h3>
<p><strong>1)</strong></p>
<ul>
<li>&quot;수&quot;,&quot;박&quot;이라는 글자를 저장해두고 하나씩 넣어줘야할지 고민했지만 바로 떠오른 풀이는 char형 배열에 글자를 하나씩 담아서 String으로 변환해주는 방식이다. </li>
</ul>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public String solution(int n) {
        String answer = &quot;&quot;;
        char[] charArray = new char[n];

        for(int i = 0; i &lt; n; i++) {
            if(i % 2 == 0) charArray[i] = &#39;수&#39;;
            else charArray[i] = &#39;박&#39;;
        }

        answer = String.valueOf(charArray);
        return answer;
    }
}</code></pre>
<p><strong>2)</strong></p>
<ul>
<li>어차피 비어있는 String이 선언되었기 때문에 반복문으로 answer에 그대로 글자를 붙이면 되기 때문에 이렇게 할 수도 있다. (나는 문제만 보고 바로 떠올리지는 못했다.🥲) </li>
</ul>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public String solution(int n) {
        String answer = &quot;&quot;;
        for (int i = 0; i &lt; n; i++) {
            answer += i % 2 == 0 ? &quot;수&quot; : &quot;박&quot;;
        }
        return answer;
    }
}</code></pre>
<p><strong>3)</strong></p>
<ul>
<li>다른 풀이를 보니 역시나 <code>StringBuilder</code>를 사용한 분들이 있었다. <code>StringBuilder</code>, <code>StringBuffer</code>의 존재에 대해 자꾸 까먹는다. </li>
</ul>
<pre><code class="language-java">import java.util.Arrays;

class Solution {
    public String solution(int n) {
        StringBuilder answer = new StringBuilder();
        for(int i = 1; i &lt;= n; i++) {
            answer.append(i % 2 == 0 ? &quot;박&quot; : &quot;수&quot;);
        }
        return answer.toString();
    }
}</code></pre>
<hr>
<p>✔️ 이건 위의 코드 1,2,3번에 대한 결과! 
<img src="https://velog.velcdn.com/images/k_moonj/post/54c5966c-caf5-4800-b2c5-512293e77590/image.JPG" alt="">
<img src="https://velog.velcdn.com/images/k_moonj/post/63d59533-456e-42f5-a626-58df89897327/image.JPG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/d32c80b5-d421-463d-bfc4-1d46706c95d0/image.JPG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ java.util.regex.PatternSyntaxException: Dangling meta character - 정규표현식 ]]></title>
            <link>https://velog.io/@k_moonj/java.util.regex.PatternSyntaxException-Dangling-meta-character</link>
            <guid>https://velog.io/@k_moonj/java.util.regex.PatternSyntaxException-Dangling-meta-character</guid>
            <pubDate>Fri, 23 Sep 2022 14:05:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/k_moonj/post/68dc38ff-2bc1-4b48-ae10-b3a4d1a341dd/image.png" alt=""></p>
<p>백준 1541번(잃어버린 괄호) 문제를 풀다가 <code>split(&quot;+&quot;)</code>에서 오류가 발생했다. 특수문자를 기준으로 문자열을 자르고 싶다면 <code>\\</code>를 문자앞에 넣어주어야 한다.  -- <code>split(&quot;\\+&quot;)</code></p>
<ul>
<li><p><code>replace</code>, <code>replaceAll</code>, <code>split</code> 
위에 나열한 함수에서 구분자를 정규표현식으로 받기 때문에 예약어로 사용한 특수문자는 에러가 발생한다. </p>
</li>
<li><p>앞에<code>\\</code>를 붙여줘야 하는 대표적인 특수문자 </p>
<blockquote>
</blockquote>
<p><code>|</code>  <code>?</code>  <code>*</code>   <code>(</code>  <code>)</code> <code>[</code> <code>]</code> <code>{</code> <code>}</code> <code>\</code></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 같은 숫자는 싫어]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B0%99%EC%9D%80-%EC%88%AB%EC%9E%90%EB%8A%94-%EC%8B%AB%EC%96%B4</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EA%B0%99%EC%9D%80-%EC%88%AB%EC%9E%90%EB%8A%94-%EC%8B%AB%EC%96%B4</guid>
            <pubDate>Fri, 16 Sep 2022 15:37:43 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
</blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12906">Level.1 : 같은 숫자는 싫어 (스택/큐)</a></p>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/d2e6221b-a377-415e-b113-ac109463c098/image.JPG" alt=""></p>
<hr>
<h3 id="💡풀이">💡풀이</h3>
<p>바로 전 값을 담아 둘<code>tempNum</code>이라는 변수를 선언해주고 문제에서 주어진 원소의 조건인 0~9 범위 밖의 값을 넣어둔다. 범위 안의 값이면 문제에서 요구하는 조건 (연속적으로 나타나는 숫자 제거)을 위한 비교가 불가능하기 때문이다. </p>
<p>if문과는 상관없이 tempNum에 num을 넣어준다. 반복문을 돌 때 tempNum에는 이전의 숫자가 들어있기 때문에 <code>tempNum != num</code>인 경우에만 tempList에 저장해준다. </p>
<ul>
<li>예를 들어, [1,1,3] 이라는 배열이 주어지는 경우를 생각해보자.
처음 for문을 돌 때 tempNum = 10 , num = 1이기 때문에 1이 tempList에 추가되고 tempNum = 1이 된다. 하지만 두 번째 for문에서는 tempNum = 1, num = 1이기 때문에 <code>tempNum = num</code> 이므로 tempList에 저장되지 않고 tempNum에는 1을 넣는다. </li>
</ul>
<pre><code class="language-java">import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        ArrayList&lt;Integer&gt; tempList = new ArrayList&lt;Integer&gt;();
        int tempNum = 10; 
        for(int num : arr) {
            if(tempNum != num) {
                tempList.add(num);
            }
            tempNum = num;
        }

        int[] answer = new int[tempList.size()];
        for(int i = 0; i &lt; answer.length; i++) {
            answer[i] = tempList.get(i);
        }

        return answer;
    }
}</code></pre>
<p><code>tempList.get(i)</code>는 해당 인덱스의 Integer 객체를 return한다. int형으로 변환하기 위해서는 <code>intValue()</code>를 해줘야 하지만 JDK 1.5부터는 자바 컴파일러가 오토 박싱과 언박싱 처리를 해주기 때문에 자동으로 변환된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스/Java] 서울에서 김서방찾기 ]]></title>
            <link>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%84%9C%EC%9A%B8%EC%97%90%EC%84%9C-%EA%B9%80%EC%84%9C%EB%B0%A9%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@k_moonj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4Java-%EC%84%9C%EC%9A%B8%EC%97%90%EC%84%9C-%EA%B9%80%EC%84%9C%EB%B0%A9%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Fri, 16 Sep 2022 00:56:59 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12919">Level 1 : 서울에서 김서방찾기</a></p>
</blockquote>
<p>문제설명 </p>
<p>String형 배열 seoul의 element중 &quot;Kim&quot;의 위치 x를 찾아, &quot;김서방은 x에 있다&quot;는 String을 반환하는 함수, solution을 완성하세요. seoul에 &quot;Kim&quot;은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.</p>
<p>제한 사항</p>
<ul>
<li>seoul은 길이 1 이상, 1000 이하인 배열입니다.</li>
<li>seoul의 원소는 길이 1 이상, 20 이하인 문자열입니다.</li>
<li>&quot;Kim&quot;은 반드시 seoul 안에 포함되어 있습니다.</li>
</ul>
<hr>
<h3 id="💡풀이">💡풀이</h3>
<pre><code class="language-java">class Solution {
    public String solution(String[] seoul) {
        String answer = &quot;&quot;;

        for (int i = 0; i &lt; seoul.length; i++) {
            if (seoul[i].equals(&quot;Kim&quot;)) {
                answer = &quot;김서방은 &quot;  + i + &quot;에 있다&quot;;
            }
        }

        return answer;
    }
}</code></pre>
<p>그냥 문제를 보고 바로 떠올린대로 for문을 사용해서 &quot;Kim&quot;이 들어있는지를 체크했다. 다른 답안들을 보니 향상된 for문을 사용하는 것이 성능 차이는 거의 없지만 가독성을 높일 수 있는 것 같아 작성해봤다. </p>
<pre><code class="language-java">int i = 0; 
for(String name : seoul) {
    if (name.eqauls(&quot;Kim&quot;)) {
        break;
    }
    i++;
}
return &quot;김서방은 &quot;  + i + &quot;에 있다&quot;;</code></pre>
<hr>
<h4 id="✨-equals-와-equalsignorecase의-차이">✨ equals 와 equalsIgnoreCase의 차이?</h4>
<p>eqaulsIgnoreCase() 는 말 그대로 case를 ignore하고 equals검사를 한다. 대소문자에 관계없이 검사하기 때문에 <code>A&quot;.equals(&quot;a&quot;)</code>는 false지만 <code>A.eqaulsIgnoreCase(&quot;a&quot;)</code>는 true이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/Java] 2217번 - 로프 ]]></title>
            <link>https://velog.io/@k_moonj/%EB%B0%B1%EC%A4%80Java-2217%EB%B2%88-%EB%A1%9C%ED%94%84</link>
            <guid>https://velog.io/@k_moonj/%EB%B0%B1%EC%A4%80Java-2217%EB%B2%88-%EB%A1%9C%ED%94%84</guid>
            <pubDate>Thu, 25 Aug 2022 02:14:24 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
<p><a href="https://www.acmicpc.net/problem/2217">2217번: 로프</a></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/k_moonj/post/48f8811c-99eb-4149-b3f4-9ef1535f6c2b/image.JPG" alt=""></p>
<h3 id="💡풀이">💡풀이</h3>
<p>N개의 로프가 주어졌을 떄 들어올릴 수 있는 물체의 최대 중량을 구해야 한다. 
예제 입력을 살펴보자. 각각 버틸 수 있는 최대 중량이 10, 15인 로프 2개인 경우에 들어올릴 수 있는최대 중량을 구해야 한다. </p>
<pre><code>15 * 2 = 30  
10 * 2 = 20 </code></pre><p>중량이 30인 경우에는 각각의 로프에 15(= 30 / 2)만큼의 중량이 걸리게 되고 10짜리 로프는 견디지 못하기 때문에 2개의 로프로 들어올릴 수 있는 최대 중량은 20이다.</p>
<p>❗ 식을 세우기 위해 다른 경우를 보자. <code>10, 20, 25, 40</code>   로프 4개인 경우는 어떨까? 꼭 모든 로프를 사용할 필요는 없다. 가능한 최대 중량은 다음과 같다. </p>
<pre><code>4개 - 10 * 4 = 40     ---&gt; ropes[0] * (4 - 0) 
3개 - 20 * 3 = 60     ---&gt; ropes[1] * (4 - 1) 
2개 - 25 * 2 = 50     ---&gt; ropes[2] * (4 - 2)
...</code></pre><p>3개를 이용하는 경우 <code>25 * 3</code>은 20짜리가 견디지 못하기 때문에 불가능하고
2개를 이용하는 경우는 <code>45 * 2</code>는 25짜리가 견디지 못한다. </p>
<p>따라서 이 경우에는 최대 중량인 60이 출력되야 할 것이다. </p>
<blockquote>
</blockquote>
<p>로프의 중량을 오름차순으로 나열했을때 <code>가장 작은 중량 x 로프의 개수</code> 부터 시작해서 차례로 비교해서 가장 큰 값을 찾아내면 된다. </p>
<h3 id="💻답안">💻답안</h3>
<pre><code class="language-java">import java.io.*;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(br.readLine());
        int[] ropes = new int[n];
        int res = 0;

        for (int i = 0; i &lt; n; i++) {
            ropes[i] = Integer.parseInt(br.readLine());
        }

        Arrays.sort(ropes);
        res = ropes[0] * n;

        for (int i = 1; i &lt; n; i++) {
            if (ropes[i] * (n - i) &gt; res) {
                res = ropes[i] * (n - i);
            }
        }

        System.out.println(res);
    }
}
</code></pre>
<hr>
<h3 id="👩💻-생각">👩‍💻 생각</h3>
<p>그리디 알고리즘은 사실 어떤 개념이 존재한다기보다는  정확한 답을 찾기 위한 탐욕적 접근법이기 때문에 내가 풀이한 방법이 정당한지 검토하는 과정이 중요하다. 하지만 가장 중요한 부분은 역시 스스로 고민해서 어떻게든 답을 찾을 수 있는 해법을 찾을 수 있는 것이라고 생각한다. 
이 문제같은 경우는 간단한 문제라서 비교적 짧은 시간에 해결법을 찾을 수 있었다. 앞으로 다양한 문제를 접하면서 깊게 생각하는 능력을 키워야 겠다.😊 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준/Java] 1789번 - 수들의 합 ]]></title>
            <link>https://velog.io/@k_moonj/%EB%B0%B1%EC%A4%80Java-1789%EB%B2%88-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A9</link>
            <guid>https://velog.io/@k_moonj/%EB%B0%B1%EC%A4%80Java-1789%EB%B2%88-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A9</guid>
            <pubDate>Mon, 22 Aug 2022 13:46:57 GMT</pubDate>
            <description><![CDATA[<h3 id="🙂-문제">🙂 문제</h3>
<blockquote>
</blockquote>
<p><a href="https://www.acmicpc.net/problem/1789">1789번 : 수들의 합</a></p>
<h3 id="✏️-접근방법">✏️ 접근방법</h3>
<p><code>서로 다른 수의 합</code>이라고 했기 때문에 </p>
<pre><code>200 = 199 + 1
    = 198 + 2 
    = 197 + + 2 + 1 
    = 196 + 3 + 1 
    = ...</code></pre><p>이런 식으로 수의 합을 만드는 경우들을 바로 떠올렸다. 하지만 이 문제에서는 최대 개수를 묻고 있기 때문에 그냥 단순히 서로 다른 수의 합을 생각하는 것이 아니라 많은 수를 더해야 한다는 것에 생각해야 한다.</p>
<p>👉 <code>서로 다른 자연수 N개의 합</code>인데 <code>N이 최대</code>라면 가장 간단한 방법은 작은 수부터 연속적으로 더해나가는 것이다. </p>
<hr>
<h3 id="💡풀이">💡풀이</h3>
<p>예를 들어, S = 15인 경우에는 아래와 같이 합을 나타낼 수 있고 N = 5이다. </p>
<pre><code>1 + 2 + 3 + 4 + 5 = 15</code></pre><p>S = 14라면 위의 식에서 1을 빼면 되니까 N = 4이다. 마찬가지로, S = 10이면 위의 식에서 5를 빼면 되기 때문에 N = 4이다. S가 9이면 6을 빼줘야 하는데 6이 없기 때문에 1과 5를 빼줘야 하므로 N = 3이 된다.</p>
<p>식을 만들기 쉽게 예시를 들어보면 아래와 같다. </p>
<blockquote>
</blockquote>
<p> S = 20 이라고 하자. 
 21 = 1 + 2 + 3 + 4 + 5 + 6  -&gt;  N = 6이지만 (21 - 20) 인 1이 식에 존재한다. 따라서 N = 6 - 1 = 5이다. </p>
<p>필요한 값은 <code>sum</code>(차례대로 더해지는 값의 결과) , <code>n</code>(찾고자 하는 값(합으로 만들어져야 하는 수)), <code>cnt</code>(숫자 개수) </p>
<p>✨
*<em>1) 찾으려는 값보다 커질때까지 1부터 차례로 더하면서 count한다. (cnt++)
2) <code>sum</code>의 값이 처음에 입력받은 수인 <code>n</code>보다 커지면 반복문을 빠져나와야 한다. 
3) count - 1을 해서 더한 숫자의 개수를 구한다. *</em></p>
<hr>
<h3 id="💻-답안">💻 답안</h3>
<pre><code class="language-java">import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        long n = Long.parseLong(br.readLine());
        long sum = 0;
        long cnt = 0;

        while (true) {
            if (sum &gt; n) {
                break;
            }
            sum += cnt + 1;
            cnt++;
        }

        System.out.println(cnt - 1);
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[엔티티 매핑]]></title>
            <link>https://velog.io/@k_moonj/%EC%97%94%ED%8B%B0%ED%8B%B0-%EB%A7%A4%ED%95%91</link>
            <guid>https://velog.io/@k_moonj/%EC%97%94%ED%8B%B0%ED%8B%B0-%EB%A7%A4%ED%95%91</guid>
            <pubDate>Tue, 16 Aug 2022 10:19:11 GMT</pubDate>
            <description><![CDATA[<h2 id="✨-객체와-테이블-매핑">✨ 객체와 테이블 매핑</h2>
<h3 id="entity">@Entity</h3>
<p><code>@Entity</code>가 붙은 클래스는 엔티티라고 하며 JPA가 관리한다. 
JPA를 사용해서 테이블과 매핑할 클래스에는 해당 어노테이션을 꼭 붙여줘야 한다. </p>
<ul>
<li>기본 생성자는 필수<ul>
<li>JPA를 구현해서 사용하는 라이브러리들이(ex.Reflection API..) 객체를 프록싱할 때 기본 생성자가 필요하기 때문이다. </li>
</ul>
</li>
<li>final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.</li>
<li>저장할 필드에 final을 사용하면 안 된다. 
(reflection으로 생성된 프록시 객체의 필드를 초기화하려면 setter를 사용하는데 final필드는 setter를 이용한 초기화가 불가능하기 때문이다.)</li>
</ul>
<h3 id="table">@Table</h3>
<p><code>@Table</code>은 엔티티와 매핑할 테이블을 지정한다. 어노테이션을 따로 붙여주지 않으면 매핑한 엔티티 이름이 자동으로 테이블 이름이 된다. </p>
<p>✔️ DDL 생성 시에 유니크 제약 조건을 만든다. </p>
<h3 id="데이터베이스-스키마-자동-생성">데이터베이스 스키마 자동 생성</h3>
<blockquote>
<p>JPA는 클래스의 매핑 정보와 데이터베이스 방언을 사용해 데이터베이스 스키마를 자동으로 생성한다. </p>
</blockquote>
<pre><code class="language-xml">&lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;create&quot; /&gt;</code></pre>
<p>persistence.xml에 위와 같은 속성을 추가하면 애플리케이션 실해 시점에 데이터베이서 테이블을 자동으로 생성한다. </p>
<p>👉 이 때 생성된 DDL은 개발장비에서만 사용해야 한다. 운영 서버에는 사용하면 안 된다. (운영 환경에서 사용할 만큼 완벽하지 않기 때문에 필요한 경우에는 적절히 다듬어 사용한다.)</p>
<p>** hibernate.hbm2ddl.auto 속성**</p>
<table>
<thead>
<tr>
<th align="center">옵션</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>create</strong></td>
<td align="center">기존 테이블을 삭제하고 다시 생성 (DROP + CREATE)</td>
</tr>
<tr>
<td align="center"><strong>create-drop</strong></td>
<td align="center">create와 같으나 종료시점에 테이블 DROP (DROP + CREATE + DROP)</td>
</tr>
<tr>
<td align="center"><strong>update</strong></td>
<td align="center">변경분만 반영(운영DB에는 사용하면 안됨)</td>
</tr>
<tr>
<td align="center"><strong>validate</strong></td>
<td align="center">엔티티와 테이블이 정상 매핑되었는지만 확인</td>
</tr>
<tr>
<td align="center"><strong>none</strong></td>
<td align="center">사용하지 않음</td>
</tr>
</tbody></table>
<p>❗운영 서버에서 <code>create</code>, <code>create-drop</code>, <code>update</code>처럼 ddl을 수정하는 옵션은 절대 사용하면 안 된다. 이 옵션들은 운영 중인 db의 테이블이나 컬럼을 삭제할 수 있기 때문이다. </p>
<ul>
<li>개발 초기 단계 : <code>create</code> 또는 <code>update</code> </li>
<li>테스트 서버 : <code>update</code> 또는 <code>validate</code> </li>
<li>스테이징과 운영 서버 : <code>validate</code> 또는 <code>none</code> </li>
</ul>
<hr>
<h2 id="✨-필드와-컬럼-매핑">✨ 필드와 컬럼 매핑</h2>
<p><strong>JPA가 제공하는 필드와 컬럼 매핑용 어노테이션</strong>  - 필요할 떄 찾아보며 사용하면 된다.</p>
<table>
<thead>
<tr>
<th align="center">어노테이션</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>@Column</strong></td>
<td align="center">컬럼 매핑</td>
</tr>
<tr>
<td align="center"><strong>@Temporal</strong></td>
<td align="center">날짜 타입 매핑</td>
</tr>
<tr>
<td align="center"><strong>@Enumerated</strong></td>
<td align="center">enum 타입 매핑</td>
</tr>
<tr>
<td align="center"><strong>@Lob</strong></td>
<td align="center">BLOB, CLOB(대형데이터) 매핑</td>
</tr>
<tr>
<td align="center"><strong>@Transient</strong></td>
<td align="center">특정 필드를 컬럼에 매핑하지 않음(매핑 무시)</td>
</tr>
</tbody></table>
<h3 id="column">@Column</h3>
<p>객체 필드를 테이블 컬럼에 매핑한다. </p>
<ul>
<li>length - 문자 길이 제약 조건, String 타입에만 사용 , 기본값 = 255 </li>
<li>nullable - null값의 허용 여부 설정 (false로 설정하면 DDL 생성시 not null 제약조건 붙음),
기본값 = true </li>
</ul>
<h3 id="enumerated">@Enumerated</h3>
<p>자바 enum타입을 매핑할 때 사용한다. </p>
<ul>
<li><code>EnumTytpe.STRING</code>을 사용하는 것이 좋다. db에 문자로 저장되기 때문에 저장된 enum의 순서가 바뀌거나 enum이 추가되도 안전하다. (<code>ORDINAL</code>은 이미 저장된 enum의 순서를 변경할 수 없다.)</li>
</ul>
<hr>
<h2 id="✨-기본-키-매핑">✨ 기본 키 매핑</h2>
<pre><code class="language-java">@Id @GeneratedValue(strategey = GeneratrionType.AUTO)
private Long id;</code></pre>
<p><strong>직접할당</strong> : <code>@Id</code>만 사용 </p>
<p><strong>자동 생성</strong> (<code>@GeneratedValue</code>)</p>
<p>&lt;전략&gt;</p>
<ul>
<li>IDENTITY : 기본 키 생성을 데이터베이스에 위임, MYSQL </li>
<li>SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키 할당 </li>
<li>TABLE : 키 생성 테이블 사용 </li>
<li>AUTO : 데이터베이스 방언에 맞춰 위의 셋 중에 하나가 선택됨 </li>
</ul>
<hr>
<p>참고 )
<a href="https://www.inflearn.com/course/ORM-JPA-Basic">자바 ORM 표준 JPA 프로그래밍 - 기본편</a> - 인프런 김영한님 강의 
자바 ORM 표준 JPA 프로그래밍 (김영한) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220810 ]]></title>
            <link>https://velog.io/@k_moonj/TIL-220810</link>
            <guid>https://velog.io/@k_moonj/TIL-220810</guid>
            <pubDate>Thu, 11 Aug 2022 01:51:57 GMT</pubDate>
            <description><![CDATA[<ul>
<li>캠프의 마지막날이었다. 포트폴리오와 이력서 작성을 하느라 너무 바쁘게 지나간 하루였고 배우는 것, 할 줄 아는 것도 중요하지만 그걸 기록으로 남겨두는 게 정말 중요하다는  생각이 들었다. 그리고 이전에 학교에서 했던 프로젝트들 중에 마무리가 제대로 되지 않아 내팽겨쳐진 것들이 있는데 프로젝트 후에도 실력을 쌓아 디벨롭했으면 좋았을 것 같다는 아쉬움이 많이 남는다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[영속성 관리 (JPA 내부 구조)]]></title>
            <link>https://velog.io/@k_moonj/%EC%98%81%EC%86%8D%EC%84%B1-%EA%B4%80%EB%A6%AC-JPA-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@k_moonj/%EC%98%81%EC%86%8D%EC%84%B1-%EA%B4%80%EB%A6%AC-JPA-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Wed, 10 Aug 2022 02:45:19 GMT</pubDate>
            <description><![CDATA[<h2 id="🎈-영속성-컨텍스트">🎈 영속성 컨텍스트</h2>
<blockquote>
</blockquote>
<h4 id="엔티티를-영구-저장하는-환경">&quot;엔티티를 영구 저장하는 환경&quot;</h4>
<pre><code class="language-java">EntityManager.persist(entity);</code></pre>
<h3 id="✔️-영속성-컨텍스트란">✔️ 영속성 컨텍스트란?</h3>
<p>영속성 컨텍스트는 논리적인 개념에 가깝기 때문에 눈에 보이지 않는다. 하나의 엔티티 매니저가 생성될 때 하나의 영속성 컨텍스트가 생성된다. 그리고 엔티티 매니저를 통해 영속성 컨텍스트에 접근할 수 있으며, 관리할 수 있다.</p>
<br>

<h3 id="✔️-엔티티-생명주기">✔️ 엔티티 생명주기</h3>
<img src="https://velog.velcdn.com/images/k_moonj/post/506ac726-0eea-4c7b-82fa-4e61c5a4373b/image.png" width=80% height=80%>

<p>엔티티에는 4가지 상태가 존재한다. </p>
<hr>
<h4 id="1-비영속-newtransient">1) 비영속 (new/transient)</h4>
<ul>
<li>영속성 컨텍스트와 전혀 관계 없는 상태 </li>
</ul>
<p>엔티티 객체를 생성하면 순수한 객체 상태인데 아직 저장하지 않았기 때문에 영속성 컨텍스트나 데이터베이스랑은 전혀 관련이 없다. </p>
<pre><code class="language-java">// 비영속
Member member = new Member();
member.setId(10L);
member.setName(&quot;Hello&quot;);</code></pre>
<h4 id="2-영속-managed">2) 영속 (managed)</h4>
<ul>
<li>영속성 컨텍스트에 저장된 상태 </li>
</ul>
<pre><code class="language-java">// 영속 
em.persist(member);</code></pre>
<p>영속 상태가 된다고 바로 DB에 저장되는 게 아니다. 트랜잭션을 커밋하는 시점에 영속성 컨텍스트에 있는 내용이 쿼리가 날라가고 DB에 저장된다. </p>
<h4 id="3-준영속-detached">3) 준영속 (detached)</h4>
<ul>
<li>영속성 컨텍스트에 저장되었다가 분리된 상태 </li>
</ul>
<pre><code class="language-java">em.detach(member);</code></pre>
<p><code>em.close()</code>나 <code>em.close()</code>를 호출해서 영속성 컨텍스트를 닫거나 초기화해도 준영속 상태가 된다. </p>
<h4 id="4-삭제-removed">4) 삭제 (removed)</h4>
<ul>
<li>객체를 삭제한 상태. 
엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다. </li>
</ul>
<pre><code class="language-java">em.remove(member);</code></pre>
</br>
<br>

<h3 id="✔️-영속성-컨텍스트의-특징">✔️ 영속성 컨텍스트의 특징</h3>
<p>영속성 컨텍스트가 엔티티를  관리하면 아래와 같은 장점이 있다. 이러한 이점이 영속성 컨텍스트가 필요한 이유이기도 하다. </p>
<blockquote>
</blockquote>
<ul>
<li>1차 캐시</li>
<li>동일성 보장</li>
<li>변경 감지 (Dirty Checking)</li>
<li>지연 로딩 (Lazy Loading) </li>
</ul>
<hr>
<h4 id="✅-엔티티-조회">✅ 엔티티 조회</h4>
<img src="https://velog.velcdn.com/images/k_moonj/post/4371e25e-3906-4c28-846c-4fba3bea254c/image.png" width=60% height=60%>

<p>영속성 컨텍스트가 가지고 있는 내부 캐시를 1차 캐시라고 한다. 영속 상태의 엔티티는 모두 이 캐시에 저장된다. </p>
<pre><code class="language-java">// 엔티티 생성 (비영속)
Member member = new Member();
member.setId(&quot;memberId&quot;);
membemr.setUsername(&quot;회원1&quot;);

// 엔티티를 영속
em.persist(member);</code></pre>
<p>저장한 memeber 객체 자체가 값이 된다. </p>
<h4 id="✅-1차-캐시에서-조회">✅ 1차 캐시에서 조회</h4>
<img src="https://velog.velcdn.com/images/k_moonj/post/68703e93-a8a4-41f5-be72-d18b3e4b620b/image.png" width=70% height=70%>

<pre><code class="language-java">// 1차 캐시에 저장 
em.persist(member);

// 1차 캐시에서 조회
Member findMember = em.find(Member.class, &quot;member1&quot;);</code></pre>
<p><code>em.find()</code>를 호출하면 JPA는 우선 영속성 컨텍스트의 1차 캐시에서 엔티티를 찾는다. member1은 1차 캐시에서 바로 조회할 수 있다.</p>
<h4 id="✅-데이터베이스에서-조회">✅ 데이터베이스에서 조회</h4>
<img src="https://velog.velcdn.com/images/k_moonj/post/3408b618-a7d1-4036-8330-746f055b608a/image.png" width=70% height=70%>

<p><code>em.find(Membmer.class, &quot;member2&quot;)</code>를 실행하면 
영속성 컨텍스트 내의 1차캐시에 member2가 없으니 DB를 조회한다. DB에서 조회한 member2를 1차 캐시에 저장한 후 반환한다. 이후에 member2를 다시 조회하면 1차캐시에 있으니 바로 불러오기때문에 성능상 이점이 있다. </p>
<p>👉 하지만 EntityManager라는 건 보통 db 트랜잭션 단위로 만들고 트랜잭션이 종료되면 같이 종료된다. 고객의 요청이 들어와 비즈니스 로직이 들고 나면 영속성 컨텍스트도 지워지기 때문에 1차 캐시도 지워진다. 위에서 말하는 이점이라는 것은 굉장히 찰나의 순간동안 얻는 것이다. 애플리케이션 전체에서 공유하는 캐시는 2차 캐시이고 1차 캐시는 데이터베이스의 한 트랜잭션 안에서만 효과가 있기 때문이다. 그래도 비즈니스 로직이 복잡해지면 이런 부분들도 도움이 된다. </p>
<h4 id="✅-영속성-엔티티의-동일성-보장">✅ 영속성 엔티티의 동일성 보장</h4>
<pre><code class="language-java">Member a = em.find(Member.class, &quot;member1&quot;);
Member b = em.find(Member.class, &quot;member1&quot;);

System.out.println(a == b);    // 동일성 비교 -&gt;  true 출력 </code></pre>
<p><code>em.find()</code>를 반복해서 호출하더라도 영속성 컨텍스트의 1차 캐시에 있는 같은 엔티티 인스턴스(member1)를 반환한다. 그렇기 때문에 a와 b는 같은 인스턴스이다. </p>
<p>💡 애플리케이션 차원에서 REPEATABLE READ 등급의 트랜잭션 격리 수준을 제공하기 때문에 반복해서 읽는 것이 가능하다. </p>
<h4 id="✅-엔티티-등록---트랜잭션을-지원하는-쓰기-지연">✅ 엔티티 등록 - 트랜잭션을 지원하는 쓰기 지연</h4>
<pre><code class="language-java">EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();

transaction.begin();

em.persist(memberA);
em.persist(memberB);</code></pre>
<p>엔티티 매니저는 트랜잭션을 커밋하기 전까지는 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 INSERT SQL을 모아둔다. </p>
<pre><code class="language-java">transaction.commit();</code></pre>
<p>커밋하는 순간에 모아뒀던 쿼리를 보내는데 이것을 <code>트랜잭션을 지원하는 쓰기 지연</code>이라고 한다. </p>
<img src="https://velog.velcdn.com/images/k_moonj/post/299b9586-6f03-4a2c-8718-c4c8dcb6d0ad/image.png" width=80% height=80%>

<p>memberA를 영속화하면 영속성 컨텍스트는 1차 캐시에 회원 엔티티를 저장하면서 동시에 회원 엔티티 정보로 INSERT 쿼리를 만든다. 만들어진 쿼리는 쓰기 지연 SQL 저장소에 보관된다.</p>
<img src="https://velog.velcdn.com/images/k_moonj/post/4b04d571-656f-430b-adf6-3be67d857261/image.png" width=80% height=80%>

<p> 이런 식으로 영속화 될 때마다 만들어진 쿼리는 트랜잭션의 커밋 시점 직전까지 저장소에 차곡차곡 쌓이게 된다. 트랜잭션을 커밋하면 엔티티 매니저는 영속성 컨텍스트를 플러시한다. </p>
<img src="https://velog.velcdn.com/images/k_moonj/post/857ee279-2155-400c-9da3-3905189a2bad/image.png" width=80% height=80%>


<h4 id="✅-변경-감지">✅ 변경 감지</h4>
<p>1차 캐시 안에는 <code>@Id</code>, <code>Entity</code>와 함께 <code>스냅샷</code>이라는 게 있다. JPA가 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는 것인데 플러시 시점에 스냅샷과 엔티티를 비교해서 어떤 엔티티가 변경되었는지 찾는다. </p>
<img src="https://velog.velcdn.com/images/k_moonj/post/0033cae5-26ee-4d57-84f0-b38776f8a4b7/image.png" width=80% height=80%>

<p><code>변경 감지</code>는 영속 상태의 엔티티에만 적용되기 때문에 비영속 상태나 준영속 상태의 엔티티는 값을 변경해도 데이터베이스에 반영되지 않는다. </p>
<hr>
<h3 id="✔️-플러시">✔️ 플러시</h3>
<blockquote>
</blockquote>
<p>👉 <code>flush()</code> : 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것! </p>
<p>영속성 컨텍스트 내의 변경사항과 데이터베이스를 맞춰주는 작업이라고 할 수 있다. </p>
<p>🙂 _위에서 트랜잭션을 커밋하면 플러시가 실행된다고 했는데 구체적으로는 아래와 같은 일이 순서대로 일어난다. _</p>
<p>1) 변경 감지가 동작해서 영속성 컨텍스트 내 모든 엔티티를 스냅샷과 비교해서 수정된 엔티티를 찾는다.</p>
<p>2) 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 보관한다.</p>
<p>3) 저장소에 있는 쿼리를 데이터베이스에 전송한다. (등록, 수정, 삭제 쿼리)</p>
<h4 id="✅--영속성-컨텍스트를-플러시하는-방법">✅  영속성 컨텍스트를 플러시하는 방법</h4>
<ul>
<li><code>em.flush()</code> 직접 호출</li>
<li>트랜잭션 커밋 시 자동 호출</li>
<li>JPQL 쿼리 실행 시 자동 호출 </li>
</ul>
<p>사실 테스트를 진행하거나 다른 프레임워크를 사용하는 경우를 제외하고는 직접 호출할 일은 거의 없다. </p>
<hr>
<p>참고 )
<a href="https://www.inflearn.com/course/ORM-JPA-Basic">자바 ORM 표준 JPA 프로그래밍 - 기본편</a> - 인프런 김영한님 강의 
자바 ORM 표준 JPA 프로그래밍 (김영한) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220809]]></title>
            <link>https://velog.io/@k_moonj/TIL-220809</link>
            <guid>https://velog.io/@k_moonj/TIL-220809</guid>
            <pubDate>Wed, 10 Aug 2022 00:38:23 GMT</pubDate>
            <description><![CDATA[<h4 id="jvm-java-virtual-machine">JVM (Java Virtual Machine)</h4>
<p>JVM(JRE,Java Runtime Environment)는 JIT 컴파일을 통해 소스코드(.java)를 CPU가 이해할 수 있는 바이너리 코드(.class)로 변환해준다.</p>
<h4 id="메소드-영역--static-영역">메소드 영역 (= static 영역)</h4>
<p>클래스 멤버 변수의 이름, 데이터 타입 같은 필드 정보들과 메서드 정보, static 변수 등이 생성되는 영역 </p>
<h4 id="스택-영역">스택 영역</h4>
<p>지역 변수, 파라미터, 리턴 값 등 임시 값이 생성되는 영역 (primitive type 8가지)</p>
<h4 id="heap-영역">Heap 영역</h4>
<p>사용자가 직접 관리가능한 영역 (사용자에 의해 메모리가 동적으로 할당 또는 해제된다)
heap size = 메모리의 1/64 (최대: 1/4)</p>
<hr>
<ul>
<li><p>4월에 설렘과 약간의 두려움으로 시작한게 엊그제 같은데 벌써 오늘이 캠프를 하며 작성하는 마지막 TIL이다. 학교 다니면서는 블로그를 만들고 공부 내용을 기록해야겠다고 생각만 하고 실천에 옮기지 못했는데 내배캠 덕분에 4개월동안 꾸준히 TIL과 WIL을 작성할 수 있었다.🙂 </p>
</li>
<li><p>매일매일 성장하는 개발자가 되고싶다는 마음가짐으로 시작한 건데 4개월 전의 나와 비교했을 때 얼마나 성장했는지 정확하게 말할 순 없지만 확실히 얻은 건 있다. 이제 내가 부족한 부분이 뭔지, 어떤 것들을 공부해야 할지, 내가 나아가야 할 방향성을 찾은 느낌이다. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220808]]></title>
            <link>https://velog.io/@k_moonj/TIL-220808</link>
            <guid>https://velog.io/@k_moonj/TIL-220808</guid>
            <pubDate>Tue, 09 Aug 2022 00:19:49 GMT</pubDate>
            <description><![CDATA[<p>개발자의 포트폴리오는 필요한 정보를 제대로 제공하는 것이 중요하다.</p>
<ul>
<li><p>프로젝트 제목/주제</p>
</li>
<li><p>Demo링크 </p>
</li>
<li><p>제작 기간 &amp; 참여 인원</p>
</li>
<li><p>사용한 기술 (기술 스택)</p>
</li>
<li><p>핵심 기능 (코드로 보여주거나 코드 링크)</p>
</li>
<li><p>트러블 슈팅 경험 / 자랑하고 싶은 코드 </p>
</li>
<li><p>회고 / 느낀점 </p>
</li>
<li><p>가독성, 오타, 링크 체크하기 !!! (중요)</p>
</li>
<li><p>문제가 생겨서 어떤 자료들을 읽어서 어떤 것들을 새롭게 알게 되었는지, 어떻게 적용했는지. 개선된 코드가 어떤 결과를 보여줬는지 문제해결과정에 대해 보여주는 게 중요하다. 코드 퀄리티는 신입이기에 당연히 낮을 수 밖에 없지만 그걸 어떻게 개선해나가는지 보여주는 게 중요하다. </p>
</li>
</ul>
<hr>
<p>갑자기 할 게 너무 많아져서 뭐부터 해야할지 모르겠지만 해야할 게 명확해졌다는 건 감사한 일이다. 포트폴리오를 작성하면서 코드 리팩토링을 계속 해나가야 겠다. 그리고 끄적여놓은 트러블슈팅이나 개발과정도 제대로 문서화하는 작업이 필요할 것 같은데...알고리즘 공부도 해야하고 이력서도 써아하고 할 게 너무 많다!! 할 일이 많을수록 이것저것 손만 대다가 시간이 흘러가지 않게 차근차근 순서를 정해 진행해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[WIL] 내배캠 16주차]]></title>
            <link>https://velog.io/@k_moonj/WIL-%EB%82%B4%EB%B0%B0%EC%BA%A0-16%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@k_moonj/WIL-%EB%82%B4%EB%B0%B0%EC%BA%A0-16%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Mon, 08 Aug 2022 01:00:55 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>알고리즘 공부와 문제풀이를 시작했는데 확실히 자료구조를 제대로 알고 있어야 문제풀 때 접근하기 쉬운 것 같다. 튜터님이 얼마나 깊게 고민할 수 있느냐를 평가하는 시험이라고 하셨는데 스스로 고민하는 시간이 정말 중요한 것 같다. 짧고 간단한 문제라도 나름대로의 과정을 나눠 생각하는 연습을 해야겠다. </p>
</li>
<li><p>이제 스프링 공부도 부지런히 하기!!.. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220805]]></title>
            <link>https://velog.io/@k_moonj/TIL-220805</link>
            <guid>https://velog.io/@k_moonj/TIL-220805</guid>
            <pubDate>Fri, 05 Aug 2022 12:08:56 GMT</pubDate>
            <description><![CDATA[<ul>
<li>할 게 너무 많아서 그런지 어느 하나에도 집중을 하지 못한 하루였다...🙁</li>
</ul>
<ul>
<li><p>어제부터 백준 문제들을 풀면서 느낀건데 기본 문제라 그런지 문제 링크를 눌러서 읽을 때마다 계속 어디선가 본 것 같은 기분이 들었다. 근데 앞 부분 문제들은 풀고 제출을 할 때마다 이미 2년 전 쯤에 c++로 제출했던 흔적이 있었다.. 아마 자료구조 듣던 시절에 풀었던 것 같은데 그걸 보니 그 때 수업만 듣고 내팽개쳐버려서 알고리즘, 자료구조 공부와 코딩테스트 준비까지 이어나가지 않은 내 자신이 너무 싫었다.ㅎㅎㅎ </p>
</li>
<li><p>이력서도 작성해야 하는데 진짜 어떻게 써야할지 막막하다. 웹 백엔드와 관련된 프로젝트 경험은 캠프에서 한 프로젝트가 전부인데 그마저도 완벽히 이해하고 진행한 게 아니라 그런지 이게 맞나..? 싶다. 이제 정말 취준을 해야할 때인데 욕심이 생겨서인지 자꾸만 너무 부족하다는 생각이 든다. (아마 이번 프로젝트를 통해 내가 부족한 부분들을 잘 알게됐고 더 제대로 협업하고 나은 프로젝트를 해보고 싶다는 생각 때문인 것 같다.) </p>
</li>
<li><p>일단 지금은 코딩테스트 준비와 CS공부에 집중해야 할 시기인 것 같다. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA 구동방식]]></title>
            <link>https://velog.io/@k_moonj/JPA-%EA%B5%AC%EB%8F%99%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@k_moonj/JPA-%EA%B5%AC%EB%8F%99%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Fri, 05 Aug 2022 00:46:37 GMT</pubDate>
            <description><![CDATA[<hr>
<h3 id="💡-jpa-구동방식">💡 JPA 구동방식</h3>
<img src="https://velog.velcdn.com/images/k_moonj/post/6f59c4c4-7e08-43cd-ad50-21e48824f715/image.png" width=80% height=80%>


<h4 id="1-entitymanagerfactory-생성">1) EntityManagerFactory 생성</h4>
<p>JPA를 시작하기 위해서는 persistence.xml에 설정정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다.</p>
<pre><code class="language-java">EntityManagerFactory emf = Persistence.createEntityManagerFactory(&quot;hello&quot;);
</code></pre>
<p>이렇게 작성해주면 META-INF/persistence.xml파일에서 이름이 hello인 영속성 유닛을 찾아 엔티티 매니저 팩토리를 생성한다. 설정 정보를 읽어서 JPA를 동작시키기 위해서는 객체를 만들고 경우에 따라 데이터 커넥션 풀을 하기 때문에 EntityManagerFactory는 만드는데 드는 비용이 상당히 크다. 그래서 애플리케이션 내에서 매번 생성하는 것이 아니라 딱 한 번만 생성해서 공유해서 사용해야 한다.  </p>
<h4 id="2-엔티티-매니저-생성">2) 엔티티 매니저 생성</h4>
<pre><code class="language-java">EntityManager em = emf.createEntityManager();</code></pre>
<p>EntityManagerFactory에서 EntityManager를 생성한다. 객체를 대신 저장해주는 Java의 컬렉션같은 존재라고 생각하면 된다. 엔티티를 관리하는 역할을 하는데 내부에서 데이터 커넥션을 유지하면서 데이터베이스와 통신한다. DB커넥션과의 밀접한 관계로 인해 여러 스레드가 접근하면 동시성 문제가 발생하기 때문에 스레드끼리 공유하거나 재사용하면 안 된다. </p>
<h4 id="3-종료">3) 종료</h4>
<p>사용이 끝난 엔티티 매니저는 반드시 종료해야 한다. 애플리케이션 종료시에는 엔티티 매니저 팩토리도 종료해야 한다. </p>
<pre><code class="language-java">em.close();

emf.close();</code></pre>
<hr>
<h3 id="트랜잭션-관리">트랜잭션 관리</h3>
<p>JPA를 통해서 가져온 Entity는 JPA가 관리한다. 트랜잭션을 커밋하는 시점에 다 체크하고 쿼리를 날린다. 비즈니스 로직이 정상적으로 동작하는 경우에는 커밋하고 예외가 발생하면 트랜잭션을 롤백한다. </p>
<pre><code class="language-java">EntityTransaction tx = em.getTransaction();

try {
    tx.begin();    //트랜잭션 시작
    logic(em);    // 비즈니스 로직 실행 
    tx.commit();    // 트랜잭션 커밋

} catch (Exception e) {
    tx.rollback();    // 예외 발생시 트랜잭션 롤백
}</code></pre>
<p>가장 중요한 점은 JPA의 모든 데이터 변경은 트랜잭션 안에서 실행되야 한다는 것이다. 
RDB는 데이터 변경을 트랜잭션 안에서 하도록 설계되어 있다. DB는 내부적으로 다 트랜잭션 개념을 가지고 있기 때문에 트랜잭션을 걸지 않아도 처리해준다. </p>
<h3 id="비즈니스-로직">비즈니스 로직</h3>
<p>등록, 수정, 삭제, 조회 작업은 엔티티 매니저를 통해 수행된다. </p>
<pre><code class="language-java">// 등록
em.persist(member);

// 수정
member.setAge(20);</code></pre>
<p>단순히 엔티티 값만 변경하면 JPA가 어떤 엔티티가 변경되었는지 커밋 시점에 체크해서 UPDATE 쿼리를 생성해 데이터베이스의 값을 변경한다. </p>
<pre><code class="language-java">// 조회 
Member findMember = em.find(Member.class, id);

// 삭제 
em.remove(member);</code></pre>
<h4 id="--find--한-건-조회">- find() : 한 건 조회</h4>
<ul>
<li>엔티티 타입과 값(@Id로 테이블의 기본 키와 매핑한 식별자 값)으로 엔티티 하나를 조회하는 가장 단순한 조회 방법</li>
</ul>
<hr>
<h3 id="✔️-jpql-java-persistence-query-language">✔️ JPQL (Java Persistence Query Language)</h3>
<blockquote>
</blockquote>
<p>✏️ <em>나이가 18살 이상인 회원을 모두 검색하고 싶다면? 위에서 설명한 find()메서드로 모두 조회할 수 있을까?</em></p>
<p>JPA를 사용하면 엔티티 객체를 중심으로 개발하고 DB에 대한 처리는 JPA에게 맡겨야 한다. 대상이 테이블이 아니라 객체이기 때문에 검색하려면 모든 데이터를 애플리케이션으로 불러와 엔티티 객체로 변경해줘야 한다. 테이블이 한 두개일 때는 상관 없지만 테이블이 수십 ~ 수백 개 되는 경우는 사실상 불가능하다. </p>
<p>👉 내가 원하는 데이터를 데이터베이스에서 불러오기 위해 JPA에서는 JPQL이라는 쿼리 언어를 사용한다. </p>
<pre><code class="language-java">List&lt;Member&gt; result = em.createQuery(&quot;select m from Member as m&quot;, Member.class)
    .getResultList();
</code></pre>
<p>❗ <code>대상이 테이블이 아니라 객체!</code>  위의 &quot;select m from Member~&quot;에서 Member는 MEMBER 테이블이 아니라 회원 엔티티 객체를 의미한다.  JPQL은 테이블을 알지 못하기 떄문에 쿼리 생성 메소드를 먼저 실행해 쿼리 객체를 생성한 후 그 객체의 getResultList() 메소드를 호출한다.  </p>
<hr>
<p>💻 *<em>참고 *</em>) </p>
<p>자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 김영한님 강의
자바 ORM 표준 JPA 프로그래밍 (김영한)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220804]]></title>
            <link>https://velog.io/@k_moonj/TIL-220804</link>
            <guid>https://velog.io/@k_moonj/TIL-220804</guid>
            <pubDate>Thu, 04 Aug 2022 13:18:47 GMT</pubDate>
            <description><![CDATA[<h4 id="반올림해서-소수점-n번째자리까지-출력하기">반올림해서 소수점 n번째자리까지 출력하기</h4>
<p><code>string.format()</code></p>
<pre><code class="language-java">// format(format, args) : 인자로 전달된 format에 맞게 문자열 return 
double pi = 3.141592;
System.out.println(Stirng.format(&quot;%.3f&quot;, n));     // 소수점 아래 3째자리까지 출력 </code></pre>
<p><code>Math.round()</code></p>
<p>round(float a) : 인자로 전달된 float를 가까운 int로 return </p>
<pre><code class="language-java">Math.round(3.1) // 3을 return </code></pre>
<hr>
<ul>
<li>아무래도 알고리즘을 풀면서 잘 모르는 문법적인 부분들, Java에 관한 중요한 내용들은 그때그때 공부하고 넘어가야 할 것 같다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 220803]]></title>
            <link>https://velog.io/@k_moonj/TIL-220803</link>
            <guid>https://velog.io/@k_moonj/TIL-220803</guid>
            <pubDate>Wed, 03 Aug 2022 14:08:52 GMT</pubDate>
            <description><![CDATA[<h4 id="hash">Hash</h4>
<ul>
<li>Hash는 &quot;전화번호부&quot;라고 생각하자.</li>
<li>대부분 그 key가 String이다.</li>
<li>put / get / getOrDefault</li>
</ul>
<h4 id="트리">트리</h4>
<ul>
<li>계층형 구조 </li>
<li>트리 구조를 배열에 저장 - 완전 이진 트리 사용 </li>
</ul>
<h4 id="dfs">DFS</h4>
<ul>
<li>끝까지 파고들어 탐색 </li>
<li>그래프의 최대 깊이만큼의 공간을 요구 (공간을 적게 씀) </li>
<li>최단경로 탐색이 어려움 </li>
</ul>
<h4 id="bfs">BFS</h4>
<ul>
<li>갈라진 모든 경우의 수를 탐색</li>
<li>최단경로 탐색이 쉽지만 공간을 많이 써야 하고 시간이 오래 걸릴 수 있음 </li>
</ul>
]]></description>
        </item>
    </channel>
</rss>