<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>radderveloper</title>
    <link>https://radderveloper.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 8 Apr 2026 23:49:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>RadderNepa</managingEditor>
    <item>
      <title>#33  기능개발</title>
      <link>https://radderveloper.tistory.com/273</link>
      <description>&lt;pre id=&quot;code_1712249371144&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Queue;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        Queue&amp;lt;Double&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();
        for(int i = 0; i &amp;lt; progresses.length; i++) {
            int tmp = (100 - progresses[i]) / speeds[i];
            if(((100 - progresses[i]) % speeds[i]) == 0) {
                queue.add((double) tmp);    
            } else {
                queue.add(tmp + 0.1);    
            } 
        }
        
        List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
        
        int deploy = 0;
        while(!queue.isEmpty()) {
            double front = queue.poll();
            deploy++; // 처음 무조건 하나는 배포
            
            while(queue.size() &amp;gt; 0 &amp;amp;&amp;amp; front &amp;gt;= queue.peek()) {
                queue.poll();
                deploy++;
            }
            
            list.add(deploy);
            deploy = 0;
        }

        int[] answer = new int[list.size()];
        for(int i = 0; i &amp;lt; list.size(); i++) {
            answer[i] = list.get(i);
        }
        return answer;
    }
}
// 100 - 90 = 10 / 10 = 1
// 100 - 90 = 10 / 9  = 1.111111111111111...

// 100 - 93 = 7  / 1  = 7;
// 100 - 30 = 70 / 30 = 2.3333...
// 100 - 55 = 45 / 5  = 9;

// 100 - 95 = 5
// 100 - 90 = 10
// 100 - 99 = 1
// 100 - 99 = 1
// 100 - 80 = 20
// 100 - 99 = 1&lt;/code&gt;&lt;/pre&gt;</description>
      <category>흥미/코딩테스트</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/273</guid>
      <comments>https://radderveloper.tistory.com/273#entry273comment</comments>
      <pubDate>Fri, 5 Apr 2024 01:49:44 +0900</pubDate>
    </item>
    <item>
      <title>#32  카펫(완전탐색)</title>
      <link>https://radderveloper.tistory.com/271</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;777&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UP02H/btsFLu69WA5/sfVv1eM43W7K7R2Y9RcNXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UP02H/btsFLu69WA5/sfVv1eM43W7K7R2Y9RcNXk/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UP02H/btsFLu69WA5/sfVv1eM43W7K7R2Y9RcNXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUP02H%2FbtsFLu69WA5%2FsfVv1eM43W7K7R2Y9RcNXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;777&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;777&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I950J/btsFHrExxym/pFhg71ROsBui0kbLswIrKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I950J/btsFHrExxym/pFhg71ROsBui0kbLswIrKk/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I950J/btsFHrExxym/pFhg71ROsBui0kbLswIrKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI950J%2FbtsFHrExxym%2FpFhg71ROsBui0kbLswIrKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;448&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[해답]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1710259257286&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    public int[] solution(int brown, int yellow) {
        int[] answer = new int[2];

        // 제곱근 판별
        double squareRoot = Math.sqrt(yellow); // 제곱근
        double flootRoot = Math.floor(squareRoot); // 소수점 제거
        
        if(squareRoot == flootRoot) { // 노란색 격자 모음이 정사각형 모양
            answer[0] = ((int) flootRoot) + 2;
            answer[1] = answer[0];
        } else { // 노란색 격자 모음이 직사각형 모양
            for(int i = 1; i &amp;lt;= yellow; i++) {  // i    = 직사각형의 가로 칸 개수
                int sero = yellow / i;          // sero = 직사각형의 세로 칸 개수
                
                // 직사각형 가로 변의 길이를 가로 칸 개수로 나누었을 때 나머지가 없다.(그래야 정사각형 모양이 된다.)
                // &amp;amp;&amp;amp;
                // 카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.(문제 조건)
                if(yellow % i == 0 &amp;amp;&amp;amp; i &amp;gt;= sero) {
                    int brown_garo = (i + 2) * 2;
                    int brown_sero = sero * 2;
                    if((brown_garo + brown_sero) == brown) {
                        answer[0] = (i + 2);
                        answer[1] = sero + 2;
                        break;
                    }
                }
            }
        }
        return answer; // 카펫의 [가로, 세로] 크기를 순서대로 배열에 담아 return                                            
    }
}
// 중앙에는 노란색으로 칠해져 있고 '테두리 1줄'은 갈색으로 칠해져 있는 격자 모양 카펫
// 카펫의 노란색과 갈색으로 색칠된 격자의 개수는 기억 but 전체 카펫의 '크기'는 기억하지 못했습니다.
// 카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.
// (가로 길이 = 세로 길이) or (가로 길이 &amp;gt; 세로 길이)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1710260094637&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[문제 해결 흐름]
0. yellow 타일의 모양을 먼저 구하고, 이를 기반으로 brown 타일의 모양을 구하자

1. CASE를 나눴다.(brown 타일의 갯수를 세는 방법이 다를 것 같다고 예상되어 case를 나눴다.)
CASE1) 중앙에 모이는 노란색 격자가 정사각형인 경우
CASE2) 중앙에 모이는 노란색 격자가 정사각형이 아닌 경우(=직사각형)
CASE3) 정사각형도, 직사각형도 아닌 경우 &amp;rarr; &quot;설마 이런 모양으로 문제를 내겠어&quot; 라는 생각으로 머리속에서 case 분류만 했지 별도의 로직을 세우지는 않았다.(문제에서 &quot;이런 모양도 있을 수 있다 or 이런 모양은 없다&quot; 처럼 조금 더 자세하게 설명해주면 좋았을 것 같다.)

2. CASE1, CASE2에서 정사각형 or 직사각형 여부를 판단하기 위해 아래의 코드를 이용했다.
double squareRoot = Math.sqrt(yellow); // 제곱근
double flootRoot = Math.floor(squareRoot); // 소수점 제거
if(squareRoot == flootRoot) {......}

2-1. 노란색 격자가 정사각형인 경우
=&amp;gt; 그것을 둘러싸는 brown 타일의 가로, 세로 길이는 모두 (노란색 정사각형 한 변의 길이 + 2)
=&amp;gt; brown 타일의 가로, 세로 길이 = 카펫의 [가로, 세로] 크기

3. 노란색 격자가 정사각형이 아닌 경우(=직사각형)
=&amp;gt; 우선 노란색 타일이 어떠한 모양으로 있는지를 알아내는 것이 관건이었다.
=&amp;gt; 여기서는 문제의 전제 조건인 [카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.]를 이용했다.

for(int i = 1; i &amp;lt;= yellow; i++) {  // i    = 직사각형의 가로 칸 개수
    int sero = yellow / i;          // sero = 직사각형의 세로 칸 개수

    // 직사각형 가로 변의 길이를 가로 칸 개수로 나누었을 때 나머지가 없다.(그래야 정사각형 모양이 된다.)
    // &amp;amp;&amp;amp;
    // 카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.(문제 조건)
    if(yellow % i == 0 &amp;amp;&amp;amp; i &amp;gt;= sero) {
    
 =&amp;gt; (i &amp;gt;= sero) : 해당 조건을 이용해 우선 노란색 타일의 모양을 구했다.
 
 4.
 - (겹치는 부분 제외) brwon 타일의 가로 길이 = 노란색 타일의 가로 길이 + 2
 - (겹치는 부분 제외) brwon 타일의 세로 길이 = 노란색 타일의 세로 길이
 - 위와 같기에 [{(노란색 타일의 가로 길이 + 2) * 2} + (노란색 타일의 세로 길이) * 2] = 인자로 주어진 brwon 타일 개수
int brown_garo = (i + 2) * 2;
int brown_sero = sero * 2;
if((brown_garo + brown_sero) == brown) {
    answer[0] = (i + 2);
    answer[1] = sero + 2;
    break;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdlKPU/btsFJoAlNv0/n0OPtFVMKDHNXx1MpUynEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdlKPU/btsFJoAlNv0/n0OPtFVMKDHNXx1MpUynEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdlKPU/btsFJoAlNv0/n0OPtFVMKDHNXx1MpUynEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdlKPU%2FbtsFJoAlNv0%2Fn0OPtFVMKDHNXx1MpUynEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;462&quot; height=&quot;386&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;386&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>흥미/코딩테스트</category>
      <category>완전탐색</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/271</guid>
      <comments>https://radderveloper.tistory.com/271#entry271comment</comments>
      <pubDate>Wed, 13 Mar 2024 01:20:26 +0900</pubDate>
    </item>
    <item>
      <title>#31  모의고사(완전탐색)</title>
      <link>https://radderveloper.tistory.com/270</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;* 이런, 완전탐색을 이진탐색(Binary Search)으로 착각한 상태에서 이번 문제를 풀어버렸다.(정확히는 해답을 보기전까지 그렇게 생각하고 있었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;* &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;&lt;b&gt;도대체 언제부터... 이진탐색을 사용중이라고 착각한 거지?&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 완전탐색의 설명 자체가 아래와 같이 간단명료하게 나와있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJuBQ4/btsFJBFkvAI/X0fNvMTzTpuutVhj9pFDu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJuBQ4/btsFJBFkvAI/X0fNvMTzTpuutVhj9pFDu0/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJuBQ4/btsFJBFkvAI/X0fNvMTzTpuutVhj9pFDu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJuBQ4%2FbtsFJBFkvAI%2FX0fNvMTzTpuutVhj9pFDu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;828&quot; height=&quot;122&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;812&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PA6Ea/btsFFYvDE61/PgaoqWQ9uXTN3GULKcKraK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PA6Ea/btsFFYvDE61/PgaoqWQ9uXTN3GULKcKraK/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PA6Ea/btsFFYvDE61/PgaoqWQ9uXTN3GULKcKraK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPA6Ea%2FbtsFFYvDE61%2FPgaoqWQ9uXTN3GULKcKraK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;812&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;812&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[해답]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 3명의 수포자가 각각 답을 몇 개 맞추었는지를 밝혀내는 것은 어렵지 않았다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[내가 문제를 풀지 못 한 원인]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1) return 하는 answer 값을 어떻게 만들어야할지 도저히 감이 잡히지가 않았던 것이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2) 1번의 연장선으로서 문제를 똑바로 안 읽었다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 문제는 분명히 &lt;i&gt;&lt;b&gt;&quot;가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return&quot;&lt;/b&gt;&lt;/i&gt; 라고 말했다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이것을 제대로 이해를 못해 &lt;i&gt;&lt;b&gt;&quot;&lt;i&gt;&lt;b&gt;전체 수포자를&lt;/b&gt;&lt;/i&gt; 문제를 많이 맞힌 순서대로 담아서 return&quot;&lt;/b&gt;&lt;/i&gt; 이라고 이해했다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 사실 윗 말을 이해했어도 그걸 구현했을지는 의문이지만 어쨌든 문제를 똑바로 안 읽고 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;냅다 코드부터 친 것이 화근이었다. &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;그야말로 기본기 부족에서 비롯된 문제였다.&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1710170821913&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.
// 1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, (이후 반복됨) 1, 2, 3, 4, 5, ...
// 2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, (이후 반복됨) 2, 1, 2, 3, 2, 4, 2, 5, ...
// 3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, (이후 반복됨) 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

import java.util.*;
import java.util.stream.*;

class Solution {
    public int[] solution(int[] answers) {       
        int[] first = {1, 2, 3, 4, 5};
        int[] two   = {2, 1, 2, 3, 2, 4, 2, 5};
        int[] three = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
        
        int firstLeng = 0; int twoLeng = 0; int threeLeng = 0;      
        int firstCnt = 0; int twoCnt = 0; int threeCnt = 0;
        
        for(int i = 0; i &amp;lt; answers.length; i++) {
            int tmp = answers[i];
            
            if(tmp == first[firstLeng]) firstCnt++;
            if(tmp == two[twoLeng]) twoCnt++;
            if(tmp == three[threeLeng]) threeCnt++;
            
            firstLeng++; twoLeng++; threeLeng++;

            if(firstLeng == first.length) firstLeng = 0;
            if(twoLeng == two.length) twoLeng = 0;
            if(threeLeng == three.length) threeLeng = 0;
        }
        
        List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
        int max = Math.max(firstCnt, Math.max(twoCnt, threeCnt)); // 3개 중 가장 큰 수 찾기
        // 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬
        if(max == firstCnt) list.add(1); 
        if(max == twoCnt) list.add(2);
        if(max == threeCnt) list.add(3);
        
        return list.stream().mapToInt(Integer::intValue).toArray();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLYKp6/btsFJlvYjnQ/hQwdt6J31rXkTGMlY1oeO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLYKp6/btsFJlvYjnQ/hQwdt6J31rXkTGMlY1oeO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLYKp6/btsFJlvYjnQ/hQwdt6J31rXkTGMlY1oeO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLYKp6%2FbtsFJlvYjnQ%2FhQwdt6J31rXkTGMlY1oeO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;603&quot; height=&quot;642&quot; data-origin-width=&quot;603&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코드가 지저분하다고 느껴질 뿐 아래까지 구현하는 것은 어렵지 않았다.&lt;/p&gt;
&lt;pre id=&quot;code_1710170854297&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] first = {1, 2, 3, 4, 5};
int[] two   = {2, 1, 2, 3, 2, 4, 2, 5};
int[] three = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};

int firstLeng = 0; int twoLeng = 0; int threeLeng = 0;      
int firstCnt = 0; int twoCnt = 0; int threeCnt = 0;

for(int i = 0; i &amp;lt; answers.length; i++) {
    int tmp = answers[i];

    if(tmp == first[firstLeng]) firstCnt++;
    if(tmp == two[twoLeng]) twoCnt++;
    if(tmp == three[threeLeng]) threeCnt++;

    firstLeng++; twoLeng++; threeLeng++;

    if(firstLeng == first.length) firstLeng = 0;
    if(twoLeng == two.length) twoLeng = 0;
    if(threeLeng == three.length) threeLeng = 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아래 부분을 구현하지 못 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1710170899911&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
int max = Math.max(firstCnt, Math.max(twoCnt, threeCnt)); // 3개 중 가장 큰 수 찾기
// 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬
if(max == firstCnt) list.add(1); 
if(max == twoCnt) list.add(2);
if(max == threeCnt) list.add(3);

return list.stream().mapToInt(Integer::intValue).toArray();&lt;/code&gt;&lt;/pre&gt;</description>
      <category>흥미/코딩테스트</category>
      <category>완전탐색</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/270</guid>
      <comments>https://radderveloper.tistory.com/270#entry270comment</comments>
      <pubDate>Tue, 12 Mar 2024 00:29:40 +0900</pubDate>
    </item>
    <item>
      <title>#30  폰켓몬</title>
      <link>https://radderveloper.tistory.com/269</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEOYPb/btsFAjy7rLl/cb7etpzqeyUMp1EBNWBjH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEOYPb/btsFAjy7rLl/cb7etpzqeyUMp1EBNWBjH1/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEOYPb/btsFAjy7rLl/cb7etpzqeyUMp1EBNWBjH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEOYPb%2FbtsFAjy7rLl%2Fcb7etpzqeyUMp1EBNWBjH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;746&quot; height=&quot;722&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uvTIZ/btsFyNtTgZ5/F5Kh9LbGMrYUpWIiSTsI2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uvTIZ/btsFyNtTgZ5/F5Kh9LbGMrYUpWIiSTsI2K/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uvTIZ/btsFyNtTgZ5/F5Kh9LbGMrYUpWIiSTsI2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuvTIZ%2FbtsFyNtTgZ5%2FF5Kh9LbGMrYUpWIiSTsI2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;735&quot; height=&quot;640&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[해답]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1709739456540&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int[] nums) {
        // 1.
        // 반복문을 돌면서 폰켓몬 번호대로 map에 넣는다. ==&amp;gt; map.put(폰켓몬 번호, 폰켓몬 번호);
        // 풀이의 키포인트는 key의 개수이기에 value는 중요하지 않다.
        
        // 2.
        // 반복문이 끝난 후 keySet 메소드를 이용해 key의 개수를 알아낸다.(key의 개수 = 폰켓몬의 종류 개수)
        
        // 3.
        // 가져갈 수 있는 폰켓몬 마릿수 = nums.length / 2
        
        // 3.
        // 경우의 수는 총 3가지
        // 1. 폰켓몬의 종류 개수 &amp;gt; 가져갈 수 있는 폰켓몬 마릿수 ==&amp;gt; 가져갈 수 있는 폰켓몬 마릿수
        // 2. 폰켓몬의 종류 개수 &amp;lt; 가져갈 수 있는 폰켓몬 마릿수 ==&amp;gt; 폰켓몬의 종류 개수
        // 3. 폰켓몬의 종류 개수 = 가져갈 수 있는 폰켓몬 마릿수 ==&amp;gt; 둘 중 아무거나 해도 상관 없음
        
        Map&amp;lt;Integer, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        for(int num : nums) {
            map.put(num, num);
        }
        
        int answer = 0;                     // return 값
        int monster = map.keySet().size();  // 폰켓몬의 종류 개수
        int take = nums.length / 2;         // 가져갈 수 있는 폰켓몬 마릿수
        
        // if(monster &amp;gt; take) {
        //     answer = take;
        // } else if(monster &amp;lt;= take) {
        //     answer = monster;
        // }
        // return answer;
        
        // 결국은 최소값을 찾는거라 아래처럼 간단하게 return 해도 됨
        return Math.min(monster, take);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVBS1E/btsFBI5684S/k9bAm7u90pDsBjyr2kBN2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVBS1E/btsFBI5684S/k9bAm7u90pDsBjyr2kBN2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVBS1E/btsFBI5684S/k9bAm7u90pDsBjyr2kBN2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVBS1E%2FbtsFBI5684S%2Fk9bAm7u90pDsBjyr2kBN2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;687&quot; height=&quot;737&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>흥미/코딩테스트</category>
      <category>Key-value쌍으로 데이터를 빠르게 찾아</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <category>해시</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/269</guid>
      <comments>https://radderveloper.tistory.com/269#entry269comment</comments>
      <pubDate>Thu, 7 Mar 2024 00:39:12 +0900</pubDate>
    </item>
    <item>
      <title>#29  올바른 괄호</title>
      <link>https://radderveloper.tistory.com/268</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아직 안 풀었는데 나만의 우스꽝스러운 생각을 기억에서 지우기 싫어 먼저 글을 저질러버렸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJa7E8/btsFqMhsZ60/6pHsY0RdpDo5Xrr4hu98g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJa7E8/btsFqMhsZ60/6pHsY0RdpDo5Xrr4hu98g1/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJa7E8/btsFqMhsZ60/6pHsY0RdpDo5Xrr4hu98g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJa7E8%2FbtsFqMhsZ60%2F6pHsY0RdpDo5Xrr4hu98g1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;748&quot; height=&quot;856&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 문제 조건 자체가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Stack 혹은 Queue를 이용해 풀라고 했다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 근데 오늘 길을 걷다 청개구리를 닮은 돌멩이를 봐서 그런지 이상하게 그렇게 풀기가 싫었다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 그래서 아래와 같이 변화구를 던져봤다. 개굴&lt;/p&gt;
&lt;pre id=&quot;code_1709562313663&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    boolean solution(String s) {
        boolean answer = true;
        
        // 1. 처음이 ')' or 끝이 '(' 로 끝나면 false 처리
        // 이 경우 배열로 자르고 Stack을 이용하고 자시고 할 필요 없음(리소스 줄이자)
        if(s.charAt(0) == ')' || s.charAt(s.length() - 1) == '(') {
            return false;
        }
        
        // 2. &quot;()()&quot; 같이 이쁜(?) 모양일 경우에도 간단하게 replace 사용
        String afterReplace = s.replace(&quot;()&quot;, &quot;&quot;);
        if(afterReplace.length() == 0) {
            return true;
        }
        
        String[] tmp = afterReplace.split(&quot;&quot;);
        int left = 0; int right = 0;
        for(String str : tmp) {
            if(&quot;(&quot;.equals(str)) {
                left += 1;
            } else if(&quot;)&quot;.equals(str)) {
                right += 1;
            }
        }
        
        if(left == right) {
            return true;
        } else {
            return false;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;근데 역시나 문제는 풀리지 않았다. &lt;/span&gt;근데 또 놀라운건, 대부분의 문제를 통과했다는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lX7HC/btsFuOr4b92/GXKjkeOKWWr6LwI0qHk6k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lX7HC/btsFuOr4b92/GXKjkeOKWWr6LwI0qHk6k0/img.png&quot; data-alt=&quot;정확성 테스트에 한 번 더 놀라 자빠졌다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lX7HC/btsFuOr4b92/GXKjkeOKWWr6LwI0qHk6k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlX7HC%2FbtsFuOr4b92%2FGXKjkeOKWWr6LwI0qHk6k0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;708&quot; height=&quot;587&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정확성 테스트에 한 번 더 놀라 자빠졌다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[24.03.06]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 무친,;; 아래와 같이 하니까 결국 풀림&lt;/p&gt;
&lt;pre id=&quot;code_1709733076201&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    boolean solution(String s) {
        boolean answer = true;
        
        // 1. 처음이 ')' or 끝이 '(' 로 끝나면 false 처리
        // 이 경우 배열로 자르고 Stack을 이용하고 그럴 필요가 없다.(리소스 줄이자)
        if(s.charAt(0) == ')' || s.charAt(s.length() - 1) == '(') {
            return false;
        }
        
        // 2. &quot;()()&quot; 같이 정갈한(?) 모양일 경우에도 간단하게 replace 사용
        String afterReplace = s.replace(&quot;()&quot;, &quot;&quot;);
        if(afterReplace.length() == 0) {
            return true;
        } else {
            // ()))))((((() 같은 경우를 가정하고 한 번더 1번 방법을 사용
            if(afterReplace.charAt(0) == ')' || afterReplace.charAt(afterReplace.length() - 1) == '(') {
                return false;
            }   
        }
        
        String[] tmp = afterReplace.split(&quot;&quot;);
        int left = 0; int right = 0;
        for(String str : tmp) {
            if(&quot;(&quot;.equals(str)) {
                left += 1;
            } else if(&quot;)&quot;.equals(str)) {
                right += 1;
            }
        }
        
        if(left == right) {
            return true;
        } else {
            return false;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;827&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7oWOH/btsFA9JC94r/ky2QDl0LHdgHbhHyKdoBI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7oWOH/btsFA9JC94r/ky2QDl0LHdgHbhHyKdoBI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7oWOH/btsFA9JC94r/ky2QDl0LHdgHbhHyKdoBI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7oWOH%2FbtsFA9JC94r%2Fky2QDl0LHdgHbhHyKdoBI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;693&quot; height=&quot;827&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;[해답] - 정상적으로 문제 해결 시 업로드 예정 &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;b&gt;[24.03.06]&lt;/b&gt; 정상적으로 풀어봄&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- 아래의 글의 정리 부분을 먼저 참고하자&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/93&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.02.02 - [CS/자료구조 및 알고리즘] - #6 Stack(스택) - 개념(FILO : First In Last Out)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1709735683337&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;#6 Stack(스택) - 개념(FILO : First In Last Out)&quot; data-og-description=&quot;● Stack이란? - Stack은 단순한 규칙을 가지고 있는 리스트이다. 여기서 규칙은 FILO(First In Last Out)이다. - FILO(First In Last Out) : 먼저 들어간 데이터가 나중에 나오는 규칙 ex) 10명의 사람이 모두 1층에&quot; data-og-host=&quot;radderveloper.tistory.com&quot; data-og-source-url=&quot;https://radderveloper.tistory.com/93&quot; data-og-url=&quot;https://radderveloper.tistory.com/93&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mRo82/hyVxDfVU9a/mOMF3n7rUxMlR42GK8Rlsk/img.png?width=800&amp;amp;height=500&amp;amp;face=0_0_800_500,https://scrap.kakaocdn.net/dn/qWDDA/hyVxDNLHKW/CW6W0iv1r2ioJlStHFcvG1/img.png?width=800&amp;amp;height=500&amp;amp;face=0_0_800_500,https://scrap.kakaocdn.net/dn/D69Kg/hyVxtj5eM7/sg1kwsz4IP5RXWOvGJTh41/img.png?width=1246&amp;amp;height=780&amp;amp;face=0_0_1246_780&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/93&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://radderveloper.tistory.com/93&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mRo82/hyVxDfVU9a/mOMF3n7rUxMlR42GK8Rlsk/img.png?width=800&amp;amp;height=500&amp;amp;face=0_0_800_500,https://scrap.kakaocdn.net/dn/qWDDA/hyVxDNLHKW/CW6W0iv1r2ioJlStHFcvG1/img.png?width=800&amp;amp;height=500&amp;amp;face=0_0_800_500,https://scrap.kakaocdn.net/dn/D69Kg/hyVxtj5eM7/sg1kwsz4IP5RXWOvGJTh41/img.png?width=1246&amp;amp;height=780&amp;amp;face=0_0_1246_780');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;#6 Stack(스택) - 개념(FILO : First In Last Out)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;● Stack이란? - Stack은 단순한 규칙을 가지고 있는 리스트이다. 여기서 규칙은 FILO(First In Last Out)이다. - FILO(First In Last Out) : 먼저 들어간 데이터가 나중에 나오는 규칙 ex) 10명의 사람이 모두 1층에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;radderveloper.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1709736102420&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    boolean solution(String s) {
        boolean answer = true;
        
        // 1. 처음이 ')' or 끝이 '(' 로 끝나면 false 처리
        if(s.charAt(0) == ')' || s.charAt(s.length() - 1) == '(') {
            return false;
        }
        
        // 2. &quot;()()&quot; 같이 정갈한(?) 모양일 경우에도 간단하게 replace 사용
        String s_replace = s.replace(&quot;()&quot;, &quot;&quot;);
        if(s_replace.length() == 0) {
            return true;
        }
        
        // 3. 다시 한 번 1번 방법 사용
        if(s_replace.charAt(0) == ')' || s_replace.charAt(s_replace.length() - 1) == '(') {
            return false;
        }

        // 4. Stack 사용
        // 1단계, &quot;(&quot; 만나면 stack에 넣는다. ==&amp;gt; push()
        // 2단계, &quot;)&quot; 만나면 stack에서 가장 최근에 들어온 &quot;(&quot;를 꺼내서 지운다. ==&amp;gt; pop()
        // 3단계, 반복문을 다 돌고난 후 stack이 비어있으면 true 아니면 false 반환
        String[] arr = s_replace.split(&quot;&quot;);
        Stack&amp;lt;String&amp;gt; stack = new Stack&amp;lt;&amp;gt;();
        for(String str : arr) {
            if(&quot;)&quot;.equals(str) &amp;amp;&amp;amp; stack.empty()) {
                return false;
            } else if(&quot;(&quot;.equals(str)) {
                stack.push(str);    
            } else {
                stack.pop(); // Stack 맨 위 요소 제거
            }
        }       
        
        if(stack.empty()) {
            return true;
        }
        return false;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위의 코드에서 1~3번 방법은 4번의 stack 방법까지 오기 전에 미리 필터링할 만한 것은 다 걸러줘서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;불필요하게 들어가는 리소스를 줄이기 위해&lt;/b&gt;&lt;/span&gt; 그대로 가져왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNzE0z/btsFyPrHz1j/cHCDTdpEbIYNGZufonG2Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNzE0z/btsFyPrHz1j/cHCDTdpEbIYNGZufonG2Yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNzE0z/btsFyPrHz1j/cHCDTdpEbIYNGZufonG2Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNzE0z%2FbtsFyPrHz1j%2FcHCDTdpEbIYNGZufonG2Yk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;801&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 그리고 무엇보다 1~3번 방법을 주석 처리하고 Stack 방법만 이용하면 아래 같은 사태가 발생한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;827&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGFJz6/btsFACLUb6N/IcWRebCTUJI7XxEBFtMk3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGFJz6/btsFACLUb6N/IcWRebCTUJI7XxEBFtMk3k/img.png&quot; data-alt=&quot;풀이 로직은 맞는데 시간이 많이 들어가서 틀림 처리 되는 것 같다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGFJz6/btsFACLUb6N/IcWRebCTUJI7XxEBFtMk3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGFJz6%2FbtsFACLUb6N%2FIcWRebCTUJI7XxEBFtMk3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;691&quot; height=&quot;827&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;827&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;풀이 로직은 맞는데 시간이 많이 들어가서 틀림 처리 되는 것 같다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>흥미/코딩테스트</category>
      <category>Stack</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/268</guid>
      <comments>https://radderveloper.tistory.com/268#entry268comment</comments>
      <pubDate>Mon, 4 Mar 2024 23:28:23 +0900</pubDate>
    </item>
    <item>
      <title>#28  같은 숫자는 싫어 with Stack</title>
      <link>https://radderveloper.tistory.com/267</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JhKKB/btsFkWW7RDL/kPRKkhRIuHhu2UlUUYlELK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JhKKB/btsFkWW7RDL/kPRKkhRIuHhu2UlUUYlELK/img.png&quot; data-alt=&quot;출처 : https://school.programmers.co.kr&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JhKKB/btsFkWW7RDL/kPRKkhRIuHhu2UlUUYlELK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJhKKB%2FbtsFkWW7RDL%2FkPRKkhRIuHhu2UlUUYlELK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;760&quot; height=&quot;712&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://school.programmers.co.kr&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[해답]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 문제 조건 자체가 &lt;b&gt;Stack 혹은 Queue를 이용해 풀라고 했기에&lt;/b&gt; Stack을 이용해 풀었다.&lt;/p&gt;
&lt;pre id=&quot;code_1708874431980&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.util.stream.*;

public class Solution {
    public int[] solution(int []arr) {
        Stack&amp;lt;Integer&amp;gt; stack = new Stack&amp;lt;&amp;gt;();
        
        // 제네릭에는 원시형 타입이 들어가지 않기에 Integer List로 변환
        List&amp;lt;Integer&amp;gt; arrInteger = Arrays.stream(arr).boxed().collect(Collectors.toList());
        
        for(Integer num : arrInteger) {
            if(stack.empty() || (stack.peek() != num)) { // stack이 비어 있을 때도 체크해줘야 함
                stack.push(num);
            }
        }
        
        // Stream을 이용해 Stack을 int Array로 변환
        int[] answer = stack.stream().mapToInt(Integer::intValue).toArray();

        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 통과는 했는데 아마 Stream을 2번 사용해서 효율은 그닥 좋지 않은 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9DfIx/btsFgM9vBv5/xzDovPcolMOClQPfRXApEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9DfIx/btsFgM9vBv5/xzDovPcolMOClQPfRXApEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9DfIx/btsFgM9vBv5/xzDovPcolMOClQPfRXApEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9DfIx%2FbtsFgM9vBv5%2FxzDovPcolMOClQPfRXApEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1130&quot; height=&quot;800&quot; data-origin-width=&quot;1130&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이렇게 더 간략(?)하게 풀 수도 있었다.(일주일 지났는데 우연히 생각나서 다시 한 번 풀어봄)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위 풀이와 비교했을 때 arrInteger List를 굳이 만들 필요가 없었다.&lt;/p&gt;
&lt;pre id=&quot;code_1709556133470&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.util.stream.*;

public class Solution {
    public int[] solution(int []arr) {        
        Stack&amp;lt;Integer&amp;gt; stack = new Stack&amp;lt;&amp;gt;();

        for(int num : arr) {
            if(stack.empty() || !(stack.peek().intValue() == num)) { // Integer 주소 말고 숫자값 그 자체를 비교
                stack.push(Integer.valueOf(num));
            }
        }
        
        int[] answer = stack.stream().mapToInt(Integer::intValue).toArray();
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;627&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1o3I3/btsFoLDa3ci/S4yFv2vCHc9Uxs3m6xXlUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1o3I3/btsFoLDa3ci/S4yFv2vCHc9Uxs3m6xXlUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1o3I3/btsFoLDa3ci/S4yFv2vCHc9Uxs3m6xXlUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1o3I3%2FbtsFoLDa3ci%2FS4yFv2vCHc9Uxs3m6xXlUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;627&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;627&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아래와 같은 식으로 반복문만을 이용해서 풀수도 있긴 한데... 문제 전제가 그것이 아니었기에 일부러 사용하지 않았다.&lt;/p&gt;
&lt;pre id=&quot;code_1708874861246&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        ArrayList&amp;lt;Integer&amp;gt; tempList = new ArrayList&amp;lt;Integer&amp;gt;();
        int preNum = 10;
        for(int num : arr) {
            if(preNum != num) {
                tempList.add(num);
            }
            preNum = num;
        }       
        int[] answer = new int[tempList.size()];
        for(int i=0; i&amp;lt;answer.length; i++) {
            answer[i] = tempList.get(i).intValue();
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPsiPJ/btsFkWbKUVf/z7vkFWvFlLhj7OQjE06S80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPsiPJ/btsFkWbKUVf/z7vkFWvFlLhj7OQjE06S80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPsiPJ/btsFkWbKUVf/z7vkFWvFlLhj7OQjE06S80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPsiPJ%2FbtsFkWbKUVf%2Fz7vkFWvFlLhj7OQjE06S80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1116&quot; height=&quot;690&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>흥미/코딩테스트</category>
      <category>Stack</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/267</guid>
      <comments>https://radderveloper.tistory.com/267#entry267comment</comments>
      <pubDate>Mon, 26 Feb 2024 00:28:16 +0900</pubDate>
    </item>
    <item>
      <title>#1 인터넷 네트워크 - 인터넷 통신 &amp;amp; IP</title>
      <link>https://radderveloper.tistory.com/266</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #000000;&quot;&gt;&lt;b&gt;● 인터넷&amp;nbsp;통신&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 클라이언트는 한국에 있고 서버는 미국에 있다고 해보자&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이때 (&lt;span style=&quot;background-color: #fcfcfc; color: #000000; text-align: left;&quot;&gt;클라이언트 컴퓨터 - 서버 컴퓨터&lt;/span&gt;)를 &lt;u&gt;&lt;b&gt;이어주는 것이 인터넷&lt;/b&gt;&lt;/u&gt;이다.&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;- Web, HTTP 모두 인터넷 네트워크 망에 기반해서 동작한다.&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- (한국 &amp;rarr; 미국)으로 텍스트 메세지를 보낸다고 했을 때 &lt;u&gt;&lt;b&gt;인터넷 망을 통해서 데이터를 보내야 한다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt; 이때 송신되는 데이터는 수 많은 중간 노드(서버)들을 거쳐서 &lt;u&gt;&lt;b&gt;안전하게 전달돼야 한다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;ex) 해저 케이블을 거치고, 인공위성을 거치는 등&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY3ixu/btsEZSWRqrc/9y6HQponbxK1tGG6u5JkeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY3ixu/btsEZSWRqrc/9y6HQponbxK1tGG6u5JkeK/img.png&quot; data-alt=&quot;인프런 - 모든 개발자를 위한 HTTP 웹 기본 지식(김영한)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY3ixu/btsEZSWRqrc/9y6HQponbxK1tGG6u5JkeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY3ixu%2FbtsEZSWRqrc%2F9y6HQponbxK1tGG6u5JkeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;630&quot; height=&quot;340&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인프런 - 모든 개발자를 위한 HTTP 웹 기본 지식(김영한)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;그렇다면 과연 어떤 규칙으로 어떻게 넘어가는 것일까?&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #000000;&quot;&gt; &lt;b&gt;● IP(Internet Protocol)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 이것을 알기 위해 가장 먼저 알아야 하는 지식이 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;IP(Internet Protocol)&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708610046241&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[IP의 역할]
1. 지정한 IP 주소(IP Address)에 데이터 전달
2. 패킷(Packet)이라는 통신 단위로 데이터 전달&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1708611633679&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[IP의 한계]
1. 비연결성
- 패킷을 받을 대상이 없거나 서비스 or 통신 불능 상태여도 패킷 전송

2. 비신뢰성
- 중간에 패킷이 사라지면?
- 복수의 패킷을 보냈을 때 그것들이 순서대로 안오면?(패킷이 순서대로 안 오면?)

3. 프로그램 구분
- 같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이라면?&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/HTTP</category>
      <category>http</category>
      <category>인터넷</category>
      <category>인터넷 통신</category>
      <category>통신</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/266</guid>
      <comments>https://radderveloper.tistory.com/266#entry266comment</comments>
      <pubDate>Fri, 23 Feb 2024 00:04:29 +0900</pubDate>
    </item>
    <item>
      <title>#30 반납 기능</title>
      <link>https://radderveloper.tistory.com/265</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[요구 사항]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 사용자가 책을 반납할 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[API 스펙]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Method : PUT&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Path : /book/return&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Body(JSON) : {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&quot;userName&quot; : String,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&quot;bookName&quot; : String&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 결과 반환 X, HTTP Code 200이면 OK&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 대출(/book/loan)과 반납(/book/return)을 위한 HTTP Body(DTO)가 완전히 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이때 반납을 위한 DTO를 새로 만드는게 좋을까? or 재활용하는게 좋을까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cf) 대출을 위한 DTO(BookLoanRequest)는 이전 글에서 이미 만들어져 있는 상태&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qXQuR/btsxsS98htn/HtLdFyAZejq8Kp4YT7tUk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qXQuR/btsxsS98htn/HtLdFyAZejq8Kp4YT7tUk0/img.png&quot; data-alt=&quot;인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qXQuR/btsxsS98htn/HtLdFyAZejq8Kp4YT7tUk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqXQuR%2FbtsxsS98htn%2FHtLdFyAZejq8Kp4YT7tUk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1217&quot; height=&quot;472&quot; data-origin-width=&quot;1217&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이 경우 강사는 (개인적으로) 새로 만드는 것을 선호한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- why? 나중에 대출과 반납 중 한 기능에&amp;nbsp;변화가 생겼을 때 유연하게 대처할 수 있기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 반납을 위한 Table은 따로 만들 필요 없다.(user_loan_history table 그대로 사용)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. BookRetuenRequest(DTO)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696841271685&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.dto.book.request;

public class BookRetuenRequest {
    private String bookName;
    private String userName;

    public String getBookName() {
        return bookName;
    }

    public String getUserName() {
        return userName;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;831&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TyxmR/btsxH2xi1k1/BBKk2jbosM2Rvtm9auqwuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TyxmR/btsxH2xi1k1/BBKk2jbosM2Rvtm9auqwuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TyxmR/btsxH2xi1k1/BBKk2jbosM2Rvtm9auqwuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTyxmR%2FbtsxH2xi1k1%2FBBKk2jbosM2Rvtm9auqwuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1085&quot; height=&quot;831&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;831&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. Controller, Service&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Controller &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696843462380&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
public class BookController {

    private final BookService bookService;

    @PutMapping(&quot;/book/return&quot;)
    public void returnBook(@RequestBody BookRetuenRequest request) {
        bookService.returnBook(request);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Service &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696843489617&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class BookService {
    private final BookRepository bookRepository;
    private final UserLoanHistoryRepository userLoanHistoryRepository;
    private final UserRepository userRepository;

    // 생성자를 만들어 Spring bean을 주입받는다.
    public BookService(BookRepository bookRepository,
                       UserLoanHistoryRepository userLoanHistoryRepository,
                       UserRepository userRepository
    ) {
        this.bookRepository = bookRepository;
        this.userLoanHistoryRepository = userLoanHistoryRepository;
        this.userRepository = userRepository;
    }

    @Transactional
    public void returnBook(BookRetuenRequest request) {
        // 1. User table에서 User 정보를 가져온다.
        User user = userRepository.findByName(request.getUserName())
                .orElseThrow(IllegalArgumentException::new);

        // 2. 유저의 ID와 책 이름을 이용해 대출 기록을 가져온다.
        UserLoanHistory userLoanHistory = userLoanHistoryRepository
                .findByUserIdAndBookName(user.getId(), request.getBookName())
                .orElseThrow(IllegalArgumentException::new);
        
        // 3. 반납 처리
        userLoanHistory.doReturn();

        // 4. user_loan_history 테이블의 IS_RETURN 컬럼 업데이트
        // 영속성 컨텍스트의 '변경 감지' 기능으로 인해 별도의 코드나 쿼리를 작성할 필요가 없다.(그래서 아래 코드 주석 처리)
        // by @Transactional Annotation
        // userLoanHistoryRepository.save(userLoanHistory);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- UserLoanHistory에 doReturn method 추가&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696843540701&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.user.loanhistory;

import javax.persistence.*;

@Entity
public class UserLoanHistory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id = null;

    @Column(nullable = false, name = &quot;user_id&quot;)
    private long userId;

    @Column(nullable = false, name = &quot;book_name&quot;)
    private String bookName;

    @Column(nullable = false, name = &quot;is_return&quot;)
    // is_return 컬럼은 자료형이 tinyint이기 때문에 DB에 0(false) 혹은 1(true)이 들어가도 된다.
    // == boolean으로 처리해도 tinyint에 잘 매핑된다.
    private boolean isReturn;

    protected UserLoanHistory() {}

    public UserLoanHistory(long userId, String bookName, boolean isReturn) {
        this.userId = userId;
        this.bookName = bookName;
        this.isReturn = isReturn;
    }

    public boolean getIsReturn() {
        return isReturn;
    }

    // 반납 처리
    public void doReturn() {
        this.isReturn = true;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTPUh/btsxkfTddat/cMLqoYkUBESyZTxkzDFce1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTPUh/btsxkfTddat/cMLqoYkUBESyZTxkzDFce1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTPUh/btsxkfTddat/cMLqoYkUBESyZTxkzDFce1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTPUh%2FbtsxkfTddat%2FcMLqoYkUBESyZTxkzDFce1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;501&quot; height=&quot;213&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cf) userLoanHistoryRepository.save(userLoanHistory)를 주석 처리한 이유&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M9eN1/btsxSyihcSN/Z2WX6eBP5RMTcdphW7NtC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M9eN1/btsxSyihcSN/Z2WX6eBP5RMTcdphW7NtC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M9eN1/btsxSyihcSN/Z2WX6eBP5RMTcdphW7NtC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM9eN1%2FbtsxSyihcSN%2FZ2WX6eBP5RMTcdphW7NtC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;844&quot; height=&quot;525&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://radderveloper.tistory.com/262&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.09.28 - [Spring] - #27 영속성 컨텍스트&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696842145877&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;#27 영속성 컨텍스트&quot; data-og-description=&quot;- Service 계층의 주요 역할 중 하나가 트랜잭션을 관리하는 것이다. @Transactional - Spring에서 트랜잭션을 적용하는 방법 - 메소드에 @Transactional Annotation이 붙으면 메소드가 시작될 때 트랜잭션을 시&quot; data-og-host=&quot;radderveloper.tistory.com&quot; data-og-source-url=&quot;https://radderveloper.tistory.com/262&quot; data-og-url=&quot;https://radderveloper.tistory.com/262&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/blkFYG/hyT9JCp1Po/wakjiZmPWwj9qESkTeyw00/img.png?width=702&amp;amp;height=163&amp;amp;face=0_0_702_163,https://scrap.kakaocdn.net/dn/JNcbG/hyT9Enzxm5/3kD2NiEEheSMxDvp3ZNT90/img.png?width=702&amp;amp;height=163&amp;amp;face=0_0_702_163,https://scrap.kakaocdn.net/dn/bU8PhD/hyT9FUjWoG/w6IBkjPcGy6PKaF9olVwg0/img.png?width=1253&amp;amp;height=502&amp;amp;face=0_0_1253_502&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/262&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://radderveloper.tistory.com/262&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/blkFYG/hyT9JCp1Po/wakjiZmPWwj9qESkTeyw00/img.png?width=702&amp;amp;height=163&amp;amp;face=0_0_702_163,https://scrap.kakaocdn.net/dn/JNcbG/hyT9Enzxm5/3kD2NiEEheSMxDvp3ZNT90/img.png?width=702&amp;amp;height=163&amp;amp;face=0_0_702_163,https://scrap.kakaocdn.net/dn/bU8PhD/hyT9FUjWoG/w6IBkjPcGy6PKaF9olVwg0/img.png?width=1253&amp;amp;height=502&amp;amp;face=0_0_1253_502');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;#27 영속성 컨텍스트&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;- Service 계층의 주요 역할 중 하나가 트랜잭션을 관리하는 것이다. @Transactional - Spring에서 트랜잭션을 적용하는 방법 - 메소드에 @Transactional Annotation이 붙으면 메소드가 시작될 때 트랜잭션을 시&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;radderveloper.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;● 테스트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- user_loan_history table 현재 상황(0 = 대출 중 / 1 = 반납 완료)&amp;nbsp; /&amp;nbsp; user table 현재 상황&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wmAbC/btsxLjFIJgQ/RhM5d5ZROjKgEeVjq46XyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wmAbC/btsxLjFIJgQ/RhM5d5ZROjKgEeVjq46XyK/img.png&quot; data-origin-width=&quot;529&quot; data-origin-height=&quot;166&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.8745%; margin-right: 10px;&quot; data-widthpercent=&quot;64.63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wmAbC/btsxLjFIJgQ/RhM5d5ZROjKgEeVjq46XyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwmAbC%2FbtsxLjFIJgQ%2FRhM5d5ZROjKgEeVjq46XyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;529&quot; height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbaOAl/btsxH2c0WEW/1zDm84HKL5FRVUFJWyLtak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbaOAl/btsxH2c0WEW/1zDm84HKL5FRVUFJWyLtak/img.png&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;176&quot; data-is-animation=&quot;false&quot; style=&quot;width: 34.9627%;&quot; data-widthpercent=&quot;35.37&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbaOAl/btsxH2c0WEW/1zDm84HKL5FRVUFJWyLtak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbaOAl%2FbtsxH2c0WEW%2F1zDm84HKL5FRVUFJWyLtak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;307&quot; height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;user_loan_history table&amp;nbsp; /&amp;nbsp; user table&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[현재 대출 상황]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;손승완 - 주먹을 단련하는 법&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배주현 - 하체를 단련하는 법&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/npg6y/btsxp5CH33Z/CHJBHvO20ygQgqpg3k7hv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/npg6y/btsxp5CH33Z/CHJBHvO20ygQgqpg3k7hv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/npg6y/btsxp5CH33Z/CHJBHvO20ygQgqpg3k7hv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnpg6y%2Fbtsxp5CH33Z%2FCHJBHvO20ygQgqpg3k7hv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;870&quot; height=&quot;913&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZXd67/btsxsRDo5XT/3fz2R2Trun0akPl8vkHiU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZXd67/btsxsRDo5XT/3fz2R2Trun0akPl8vkHiU1/img.png&quot; data-alt=&quot;반납 완료&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZXd67/btsxsRDo5XT/3fz2R2Trun0akPl8vkHiU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZXd67%2FbtsxsRDo5XT%2F3fz2R2Trun0akPl8vkHiU1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;535&quot; height=&quot;173&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;반납 완료&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Backend/Spring</category>
      <category>jpa</category>
      <category>spring</category>
      <category>SpringBoot</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/265</guid>
      <comments>https://radderveloper.tistory.com/265#entry265comment</comments>
      <pubDate>Mon, 9 Oct 2023 18:31:14 +0900</pubDate>
    </item>
    <item>
      <title>#29 대출 기능 API</title>
      <link>https://radderveloper.tistory.com/264</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[요구사항]&lt;br /&gt;- 사용자가 책을 빌릴 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 다른 사람이 빌린 책은 또 다른 사람이 빌릴 수 없다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[API 스펙] &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Method : POST&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Path : /book/loan&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Body(JSON) : {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&quot;userName&quot; : String,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&quot;bookName&quot; : String&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 결과 반환 X, HTTP Code 200이면 OK&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.&amp;nbsp;Book&amp;nbsp;Table&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자의 대출 기록을 저장하는 새로운 테이블이 필요하다.&lt;/p&gt;
&lt;pre id=&quot;code_1696669151097&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE USER_LOAN_HISTORY (
  ID        BIGINT AUTO_INCREMENT, // 대출 기록 id
  USER_ID   BIGINT,                // 책을 빌린 유저 id
  BOOK_NAME VARCHAR(255),          // 빌린 책 이름
  IS_RETURN TINYINT(1),            // 현재 대출(0) or 반납(1) 여부
  PRIMARY KEY(ID)
);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYKoE/btsxzYuL7Kz/C8zJmgCmGQ0rFo8bjXs041/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYKoE/btsxzYuL7Kz/C8zJmgCmGQ0rFo8bjXs041/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYKoE/btsxzYuL7Kz/C8zJmgCmGQ0rFo8bjXs041/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYKoE%2FbtsxzYuL7Kz%2FC8zJmgCmGQ0rFo8bjXs041%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;362&quot; height=&quot;202&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf) user table의 id 값을 다시 1부터 시작하기 위해 AUTO_INCREMENT 값을 초기화했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://amaze9001.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://amaze9001.tistory.com/28&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696669735522&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[mySQL] AUTO_INCREMENT 값 초기화&quot; data-og-description=&quot;오늘은 mySQL AUTO_INCREMENT 값을 초기화 하는 방법을 소개하려고 합니다.아래는 [heidiSQL] 화면인데요,선택할 수 있는 기본값의 종류입니다. 그 중, 맨 아래에 있는 아이가 오늘 소개할 AUTO_INCREMENT 에&quot; data-og-host=&quot;amaze9001.tistory.com&quot; data-og-source-url=&quot;https://amaze9001.tistory.com/28&quot; data-og-url=&quot;https://amaze9001.tistory.com/28&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/B9fWo/hyT9GkV2wG/r9IIWgYYTRC4B0M2ESkVK1/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/ghfiA/hyT9DIvZEM/vftzzSxpm2EWbhmc6zkVPK/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/bovARc/hyT52C937x/X09hSiNWmkBJcBqhc8tGB0/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600&quot;&gt;&lt;a href=&quot;https://amaze9001.tistory.com/28&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://amaze9001.tistory.com/28&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/B9fWo/hyT9GkV2wG/r9IIWgYYTRC4B0M2ESkVK1/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/ghfiA/hyT9DIvZEM/vftzzSxpm2EWbhmc6zkVPK/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/bovARc/hyT52C937x/X09hSiNWmkBJcBqhc8tGB0/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[mySQL] AUTO_INCREMENT 값 초기화&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 mySQL AUTO_INCREMENT 값을 초기화 하는 방법을 소개하려고 합니다.아래는 [heidiSQL] 화면인데요,선택할 수 있는 기본값의 종류입니다. 그 중, 맨 아래에 있는 아이가 오늘 소개할 AUTO_INCREMENT 에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;amaze9001.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ASvkF/btsxp2etan2/j2z6Owe3gixiAGjVWWEkek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ASvkF/btsxp2etan2/j2z6Owe3gixiAGjVWWEkek/img.png&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;82&quot; data-is-animation=&quot;false&quot; style=&quot;width: 61.2645%; margin-right: 10px;&quot; data-widthpercent=&quot;61.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ASvkF/btsxp2etan2/j2z6Owe3gixiAGjVWWEkek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FASvkF%2Fbtsxp2etan2%2Fj2z6Owe3gixiAGjVWWEkek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cg95Bq/btsxtlxbpRw/MUIZlbQ8Zgp21G01yTyYwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cg95Bq/btsxtlxbpRw/MUIZlbQ8Zgp21G01yTyYwK/img.png&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;142&quot; data-is-animation=&quot;false&quot; style=&quot;width: 37.5727%;&quot; data-widthpercent=&quot;38.01&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cg95Bq/btsxtlxbpRw/MUIZlbQ8Zgp21G01yTyYwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcg95Bq%2FbtsxtlxbpRw%2FMUIZlbQ8Zgp21G01yTyYwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;ID 값 새로 1 부터 시작 됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. UserLoanHistory 객체 &amp;amp; UserLoanHistoryRepository&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UserLoanHistory&lt;/p&gt;
&lt;pre id=&quot;code_1696670614323&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.user.loanhistory;

import javax.persistence.*;

@Entity
public class UserLoanHistory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id = null;

    @Column(nullable = false, name = &quot;user_id&quot;)
    private long userId;

    @Column(nullable = false, name = &quot;book_name&quot;)
    private String bookName;

    @Column(nullable = false, name = &quot;is_return&quot;)
    // is_return 컬럼은 자료형이 tinyint이기 때문에 DB에 0(false) 혹은 1(true)이 들어가도 된다.
    // == boolean으로 처리해도 tinyint에 잘 매핑된다.
    private boolean isReturn;

    protected UserLoanHistory() {}

    public UserLoanHistory(long userId, String bookName, boolean isReturn) {
        this.userId = userId;
        this.bookName = bookName;
        this.isReturn = isReturn;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNy4sE/btsxsnPAsGq/Mk5ZpCVuttvfxANTK8t5hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNy4sE/btsxsnPAsGq/Mk5ZpCVuttvfxANTK8t5hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNy4sE/btsxsnPAsGq/Mk5ZpCVuttvfxANTK8t5hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNy4sE%2FbtsxsnPAsGq%2FMk5ZpCVuttvfxANTK8t5hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;816&quot; height=&quot;674&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UserLoanHistoryRepository&lt;/p&gt;
&lt;pre id=&quot;code_1696670678338&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.user.loanhistory;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserLoanHistoryRepository extends JpaRepository&amp;lt;UserLoanHistory, Long&amp;gt; {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhU8B/btsxifSUeyZ/nu94gJLEtAHsQKe7WBBuX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhU8B/btsxifSUeyZ/nu94gJLEtAHsQKe7WBBuX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhU8B/btsxifSUeyZ/nu94gJLEtAHsQKe7WBBuX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyhU8B%2FbtsxifSUeyZ%2Fnu94gJLEtAHsQKe7WBBuX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1074&quot; height=&quot;201&quot; data-origin-width=&quot;1074&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf) 현재 package 구조&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;724&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coeHfl/btsxp3YJHGz/l5gwQH5wZBxnNsHkpjzCYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coeHfl/btsxp3YJHGz/l5gwQH5wZBxnNsHkpjzCYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coeHfl/btsxp3YJHGz/l5gwQH5wZBxnNsHkpjzCYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoeHfl%2Fbtsxp3YJHGz%2Fl5gwQH5wZBxnNsHkpjzCYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;745&quot; height=&quot;724&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;724&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. DTO, Controller, Service&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DTO&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;DTO는&amp;nbsp;HTTP&amp;nbsp;Body&amp;nbsp;스펙을&amp;nbsp;보고&amp;nbsp;그에&amp;nbsp;맞게&amp;nbsp;생성&lt;/b&gt;&lt;/span&gt;하면&amp;nbsp;된다.&lt;/p&gt;
&lt;pre id=&quot;code_1696670932330&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.dto.book.request;

public class BookLoanRequest {
    private String bookName;
    private String userName;

    public String getBookName() {
        return bookName;
    }

    public String getUserName() {
        return userName;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c84qFA/btsxsTU8gGy/3NqDiWrod5PB4i9EZp2G2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c84qFA/btsxsTU8gGy/3NqDiWrod5PB4i9EZp2G2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c84qFA/btsxsTU8gGy/3NqDiWrod5PB4i9EZp2G2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc84qFA%2FbtsxsTU8gGy%2F3NqDiWrod5PB4i9EZp2G2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;878&quot; height=&quot;341&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller(loanBook method 추가)&lt;/p&gt;
&lt;pre id=&quot;code_1696674498688&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.controller.book;

import com.group.libraryapp.dto.book.request.BookCreateRequest;
import com.group.libraryapp.dto.book.request.BookLoanRequest;
import com.group.libraryapp.service.book.BookService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BookController {

    private final BookService bookService;

    // 생성자를 만들어 Spring bean을 주입받는다.
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @PostMapping(&quot;/book&quot;)
    public void saveBook(@RequestBody BookCreateRequest request) {
        bookService.saveBook(request);
    }

    @PostMapping(&quot;/book/loan&quot;)
    // HTTP body를 파싱하기 위해 @RequestBody가 필요하다.
    public void loanBook(@RequestBody BookLoanRequest request) {
        bookService.loanBook(request);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;470&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MAuTB/btsxqtXeG8I/qmNNQA1fT9nPLBEo1ffqPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MAuTB/btsxqtXeG8I/qmNNQA1fT9nPLBEo1ffqPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MAuTB/btsxqtXeG8I/qmNNQA1fT9nPLBEo1ffqPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMAuTB%2FbtsxqtXeG8I%2FqmNNQA1fT9nPLBEo1ffqPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;683&quot; height=&quot;470&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;470&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service(loanBook method 추가)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[By 앞에 들어갈 수 있는 구절]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- find :&amp;nbsp;1건을 가져온다. 반환 타입은 객체가 될 수도 있고 Optional&amp;lt;타입&amp;gt;이 될 수도 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- findAll : 쿼리의 결과물이&amp;nbsp;N개인 경우 사용, List&amp;lt;타입&amp;gt; 반환&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- exists :&amp;nbsp;쿼리 결과가 존재하는지&amp;nbsp;확인, 반환 타입은 boolean(존재 O = true / 존재 X = false)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- count :&amp;nbsp;SQL의 결과 개수를 센다. 반환 타입은 long&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ex) long&amp;nbsp;countByAge(Integer&amp;nbsp;age);&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1696674535687&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.service.book;

import com.group.libraryapp.domain.book.Book;
import com.group.libraryapp.domain.book.BookRepository;
import com.group.libraryapp.domain.user.User;
import com.group.libraryapp.domain.user.UserRepository;
import com.group.libraryapp.domain.user.loanhistory.UserLoanHistory;
import com.group.libraryapp.domain.user.loanhistory.UserLoanHistoryRepository;
import com.group.libraryapp.dto.book.request.BookCreateRequest;
import com.group.libraryapp.dto.book.request.BookLoanRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class BookService {
    private final BookRepository bookRepository;
    private final UserLoanHistoryRepository userLoanHistoryRepository;
    private final UserRepository userRepository;

    // 생성자를 만들어 Spring bean을 주입받는다.
    public BookService(BookRepository bookRepository,
                       UserLoanHistoryRepository userLoanHistoryRepository,
                       UserRepository userRepository
    ) {
        this.bookRepository = bookRepository;
        this.userLoanHistoryRepository = userLoanHistoryRepository;
        this.userRepository = userRepository;
    }

    @Transactional
    public void saveBook(BookCreateRequest request) {
        bookRepository.save(new Book(request.getName()));
    }

    @Transactional
    public void loanBook(BookLoanRequest request) {
        // 1. Book table에서 책 정보를 가져온다.
        Book book = bookRepository.findByName(request.getBookName())
                .orElseThrow(IllegalArgumentException::new);

        // 2. 빌리려는 책이 현재 대출중인지 확인
        if(userLoanHistoryRepository.existsByBookNameAndIsReturn(book.getName(), false)) {
            // 대출 O
            throw new IllegalArgumentException(&quot;이미 대출중인 책 입니다.&quot;);
        } else {
            // 대출 X
            // 3. 사용자 정보를 가져온다.
            User user = userRepository.findByName(request.getUserName())
                    .orElseThrow(IllegalArgumentException::new);

            // 4. 사용자 정보 &amp;amp; 책 정보를 이용해 userLoanHistory 저장
            userLoanHistoryRepository.save(new UserLoanHistory(user.getId(), book.getName(), false));
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1696674911307&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.user;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

// JpaRepository를 상속하는 것만으로도 UserRepository는 Spring bean으로 등록된다.
public interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {
    // name을 기준으로 조회
    // 데이터가 있으면 User 객체 반환, 없으면 null 반환
    Optional&amp;lt;User&amp;gt; findByName(String name);
    // 함수 이름이 중요하다.
    // 반드시 findByName 이라고 적어줘야한다. 함수 이름에 맞춰서 알아서 SQL이 생성돼 날라간다.
    // 'find'라고 작성하면 1개의 데이터만 가져온다.
    // 'By' 뒤에 붙는 필드 이름으로 SELECT 쿼리의 WHERE 문이 작성된다.
    // 결론 : findByName = SELECT * FROM USER WHERE NAME = ?;

    // Optional&amp;lt;User&amp;gt; findByName(String name);

    boolean existsByName(String name);

    long countByAge(Integer age);

    List&amp;lt;User&amp;gt; findAllByNameAndAge(String name, int age);

    List&amp;lt;User&amp;gt; findAllByAgeBetween(int startAge, int endAge);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1696674568501&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.book;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface BookRepository extends JpaRepository&amp;lt;Book, Long&amp;gt; {
    Optional&amp;lt;Book&amp;gt; findByName(String name);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1696674591745&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.user.loanhistory;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserLoanHistoryRepository extends JpaRepository&amp;lt;UserLoanHistory, Long&amp;gt; {
    // SELECT * FROM USER_LOAN_HISTORY WHERE BOOK_NAME = ? AND IS_RETURN = ?
    boolean existsByBookNameAndIsReturn(String bookName, boolean isReturn);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/261&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.09.26 - [Spring] - #26 JPA를 이용해 SQL 날리기 with Spring Data JPA2&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696671495286&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;#26 JPA를 이용해 SQL 날리기 with Spring Data JPA2&quot; data-og-description=&quot;1. 삭제 1. name을 기준으로 User가 있는지 확인 2. User가 있다면 DELETE 쿼리를 날린다. // JpaRepository를 상속하는 것만으로도 UserRepository는 Spring bean으로 등록된다. public interface UserRepository extends JpaReposi&quot; data-og-host=&quot;radderveloper.tistory.com&quot; data-og-source-url=&quot;https://radderveloper.tistory.com/261&quot; data-og-url=&quot;https://radderveloper.tistory.com/261&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vJdo9/hyT9CJBBzS/wvPXmv64D2m8SpM78R5JGK/img.png?width=800&amp;amp;height=326&amp;amp;face=0_0_800_326,https://scrap.kakaocdn.net/dn/bN0AJA/hyT5WJJO5c/WgN4ttWxDspVot4RQIcDq1/img.png?width=800&amp;amp;height=326&amp;amp;face=0_0_800_326,https://scrap.kakaocdn.net/dn/bciMnM/hyT9AruuhE/DoMlwa7VmCh981Qmm5k2A1/img.png?width=1613&amp;amp;height=504&amp;amp;face=0_0_1613_504&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/261&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://radderveloper.tistory.com/261&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vJdo9/hyT9CJBBzS/wvPXmv64D2m8SpM78R5JGK/img.png?width=800&amp;amp;height=326&amp;amp;face=0_0_800_326,https://scrap.kakaocdn.net/dn/bN0AJA/hyT5WJJO5c/WgN4ttWxDspVot4RQIcDq1/img.png?width=800&amp;amp;height=326&amp;amp;face=0_0_800_326,https://scrap.kakaocdn.net/dn/bciMnM/hyT9AruuhE/DoMlwa7VmCh981Qmm5k2A1/img.png?width=1613&amp;amp;height=504&amp;amp;face=0_0_1613_504');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;#26 JPA를 이용해 SQL 날리기 with Spring Data JPA2&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1. 삭제 1. name을 기준으로 User가 있는지 확인 2. User가 있다면 DELETE 쿼리를 날린다. // JpaRepository를 상속하는 것만으로도 UserRepository는 Spring bean으로 등록된다. public interface UserRepository extends JpaReposi&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;radderveloper.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;● 테스트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 user table과 book table&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5dMMS/btsxvH026pV/qYDrguG6UIScAZPuIwgc2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5dMMS/btsxvH026pV/qYDrguG6UIScAZPuIwgc2K/img.png&quot; data-origin-width=&quot;323&quot; data-origin-height=&quot;163&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.5417%; margin-right: 10px;&quot; data-widthpercent=&quot;49.11&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5dMMS/btsxvH026pV/qYDrguG6UIScAZPuIwgc2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5dMMS%2FbtsxvH026pV%2FqYDrguG6UIScAZPuIwgc2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;323&quot; height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQyvfB/btsxsQxjOaD/BMGTFU57iHvg2iZ7hcg7s0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQyvfB/btsxsQxjOaD/BMGTFU57iHvg2iZ7hcg7s0/img.png&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;188&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.89&quot; style=&quot;width: 50.2955%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQyvfB/btsxsQxjOaD/BMGTFU57iHvg2iZ7hcg7s0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQyvfB%2FbtsxsQxjOaD%2FBMGTFU57iHvg2iZ7hcg7s0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;386&quot; height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;user table / book table&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 정상 대출&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oRzSM/btsxqr6eEWI/1lj49LJ4N1RlVzy5Uh5c5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oRzSM/btsxqr6eEWI/1lj49LJ4N1RlVzy5Uh5c5K/img.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;955&quot; data-is-animation=&quot;false&quot; style=&quot;width: 26.6889%; margin-right: 10px;&quot; data-widthpercent=&quot;27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oRzSM/btsxqr6eEWI/1lj49LJ4N1RlVzy5Uh5c5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoRzSM%2Fbtsxqr6eEWI%2F1lj49LJ4N1RlVzy5Uh5c5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;955&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byjAKB/btsxp8FCLE6/xKvJm8asvlhpBNruF6NJ1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byjAKB/btsxp8FCLE6/xKvJm8asvlhpBNruF6NJ1K/img.png&quot; data-origin-width=&quot;529&quot; data-origin-height=&quot;146&quot; data-is-animation=&quot;false&quot; style=&quot;width: 72.1483%;&quot; data-widthpercent=&quot;73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byjAKB/btsxp8FCLE6/xKvJm8asvlhpBNruF6NJ1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyjAKB%2Fbtsxp8FCLE6%2FxKvJm8asvlhpBNruF6NJ1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;529&quot; height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 이미 빌린 책을 다른 사람이 빌리려고 할 때(못 빌림)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;803&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HL89t/btsxp3qSwaz/Kt9rfByY3gkPdRuRaryl91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HL89t/btsxp3qSwaz/Kt9rfByY3gkPdRuRaryl91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HL89t/btsxp3qSwaz/Kt9rfByY3gkPdRuRaryl91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHL89t%2Fbtsxp3qSwaz%2FKt9rfByY3gkPdRuRaryl91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1281&quot; height=&quot;803&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;803&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 없는 책을 빌리려고 할 때&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5jA25/btsxp7UeAjt/KbpTjkAtNPpScMaZ8No6ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5jA25/btsxp7UeAjt/KbpTjkAtNPpScMaZ8No6ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5jA25/btsxp7UeAjt/KbpTjkAtNPpScMaZ8No6ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5jA25%2Fbtsxp7UeAjt%2FKbpTjkAtNPpScMaZ8No6ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1202&quot; height=&quot;909&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;909&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 배주현 정상 대출&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8z5FS/btsxg1tPxpS/oT1JWtkHT9WaMZXryyUkK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8z5FS/btsxg1tPxpS/oT1JWtkHT9WaMZXryyUkK1/img.png&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;904&quot; data-is-animation=&quot;false&quot; style=&quot;width: 29.3635%; margin-right: 10px;&quot; data-widthpercent=&quot;29.71&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8z5FS/btsxg1tPxpS/oT1JWtkHT9WaMZXryyUkK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8z5FS%2Fbtsxg1tPxpS%2FoT1JWtkHT9WaMZXryyUkK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1186&quot; height=&quot;904&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnTzyj/btsxkivbDG5/QK2urDXmCUisIltFW3LCv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnTzyj/btsxkivbDG5/QK2urDXmCUisIltFW3LCv1/img.png&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;173&quot; data-is-animation=&quot;false&quot; style=&quot;width: 69.4737%;&quot; data-widthpercent=&quot;70.29&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnTzyj/btsxkivbDG5/QK2urDXmCUisIltFW3LCv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnTzyj%2FbtsxkivbDG5%2FQK2urDXmCUisIltFW3LCv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;173&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Backend/Spring</category>
      <category>jpa</category>
      <category>spring</category>
      <category>SpringBoot</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/264</guid>
      <comments>https://radderveloper.tistory.com/264#entry264comment</comments>
      <pubDate>Sat, 7 Oct 2023 19:31:02 +0900</pubDate>
    </item>
    <item>
      <title>#28 책 생성 API - INSERT</title>
      <link>https://radderveloper.tistory.com/263</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다음 글 부터는 먼저 코드를 작성한 다음에 강의를 들어보자&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;● 도서관에 책을 등록하는 기능&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[API 스펙]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Method : POST&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Path : /book&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- HTTP Body(JSON) : {&quot;name&quot; : String // 책 이름}&amp;nbsp; &amp;rarr; name은 필수&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 결과 반환 X, HTTP Code 200이면 OK&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이러한 구조로 만들어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnHFDn/btswcK6xDcz/G6MCRAVMyeCQNffmGtUSvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnHFDn/btswcK6xDcz/G6MCRAVMyeCQNffmGtUSvK/img.png&quot; data-alt=&quot;인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnHFDn/btswcK6xDcz/G6MCRAVMyeCQNffmGtUSvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnHFDn%2FbtswcK6xDcz%2FG6MCRAVMyeCQNffmGtUSvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;879&quot; height=&quot;317&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인프런 - 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!(최태현)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Book Table&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696249454148&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE BOOK (
   ID     BIGINT       AUTO_INCREMENT,
   NAME   VARCHAR(255) NOT NULL,
   PRIMARY KEY(ID)
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- VARCHAR(255)라고 설정한 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. JPA를 사용할 때 @Column Annotation의 length 속성의 기본값이 255이다.&amp;nbsp; &amp;rarr; @Column Annotation에서 length 속성을 생략할려고 (255)로 설정한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 문자열 필드의 경우 최적화를 해야 하는 CASE가 아니라면 조금 여유롭게 설정하는 것이 좋다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HOpzv/btswBD6qksd/pZ5KiZ7dsE0U0R8KkMYcn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HOpzv/btswBD6qksd/pZ5KiZ7dsE0U0R8KkMYcn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HOpzv/btswBD6qksd/pZ5KiZ7dsE0U0R8KkMYcn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHOpzv%2FbtswBD6qksd%2FpZ5KiZ7dsE0U0R8KkMYcn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;343&quot; height=&quot;310&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Book 객체&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696250412601&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.book;

import javax.persistence.*;

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id = null;

    @Column(nullable = false, name = &quot;name&quot;)
    private String name;

    // JPA Entity는 기본 생성자가 하나 필요하다.
    protected Book() {}

    public Book(String name) {
        // name은 필수값이다.
        if(name == null || name.isBlank()) throw new IllegalArgumentException(String.format(&quot;잘못된 name(%s)이 들어왔습니다.&quot;, name));
        this.name = name;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bajEKe/btswwQrm2yy/iDzYWo14k5ltOFIu68yWl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bajEKe/btswwQrm2yy/iDzYWo14k5ltOFIu68yWl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bajEKe/btswwQrm2yy/iDzYWo14k5ltOFIu68yWl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbajEKe%2FbtswwQrm2yy%2FiDzYWo14k5ltOFIu68yWl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1254&quot; height=&quot;527&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. BookRepository&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696251340100&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.domain.book;

import org.springframework.data.jpa.repository.JpaRepository;

public interface BookRepository extends JpaRepository&amp;lt;Book, Long&amp;gt; {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vG4Mp/btswBDk33e3/UBCObpWZCNRFt8rr9Sj3ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vG4Mp/btswBDk33e3/UBCObpWZCNRFt8rr9Sj3ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vG4Mp/btswBDk33e3/UBCObpWZCNRFt8rr9Sj3ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvG4Mp%2FbtswBDk33e3%2FUBCObpWZCNRFt8rr9Sj3ZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;920&quot; height=&quot;207&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;589&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S26nK/btswbd2doZi/lm4CW8s4MevnBLLkm6olm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S26nK/btswbd2doZi/lm4CW8s4MevnBLLkm6olm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S26nK/btswbd2doZi/lm4CW8s4MevnBLLkm6olm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS26nK%2Fbtswbd2doZi%2Flm4CW8s4MevnBLLkm6olm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;876&quot; height=&quot;589&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 강의를 듣다보니 BookRepository와 UserRepository를 왜 하필 domain package 아래에 생성하는지 궁금했다. 그냥 Repository package 아래에 생성하면 통일성이 있는데 강사는 왜 그런 것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아니나 다를까 이미 다른 사람이 이에 대해서 물어봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 강사의 답변을 보니 이건 그냥 강사 개인이 이번 Spring 강의에서 만드는 프로젝트는 이러한 구조가 더 적합한 것 같아서 그렇게 구성한 것이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 패키지를 구성하는 방법에는 정답이 없고 상황에 따라 매번 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. DTO&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;DTO는 HTTP Body 스펙을 보고 그에 맞게 생성&lt;/b&gt;&lt;/span&gt;하면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HTTP Body(JSON) : {&quot;name&quot; : String // 책 이름}&amp;nbsp; &amp;rarr; name은 필수&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1696251647280&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package com.group.libraryapp.dto.book.request;

public class BookCreateRequest {
    private String name;

    public String getName() {
        return this.name;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cM63kB/btswbeUjZzR/EdrrrKzts8Of3GUAgFlfoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cM63kB/btswbeUjZzR/EdrrrKzts8Of3GUAgFlfoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cM63kB/btswbeUjZzR/EdrrrKzts8Of3GUAgFlfoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcM63kB%2FbtswbeUjZzR%2FEdrrrKzts8Of3GUAgFlfoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;855&quot; height=&quot;238&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b08p3L/btswwR4SJFl/bySOCuFL2lKAS419kHdThk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b08p3L/btswwR4SJFl/bySOCuFL2lKAS419kHdThk/img.png&quot; data-alt=&quot;BookCreateRequest class 위치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b08p3L/btswwR4SJFl/bySOCuFL2lKAS419kHdThk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb08p3L%2FbtswwR4SJFl%2FbySOCuFL2lKAS419kHdThk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;892&quot; height=&quot;603&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;BookCreateRequest class 위치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. Controller &amp;amp; Service&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1696254040553&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Controller]

package com.group.libraryapp.controller.book;

import com.group.libraryapp.dto.book.request.BookCreateRequest;
import com.group.libraryapp.service.book.BookService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BookController {

    private final BookService bookService;

    // 생성자를 만들어 Spring bean을 주입받는다.
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @PostMapping(&quot;/book&quot;)
    public void saveBook(@RequestBody BookCreateRequest request) {
        bookService.saveBook(request);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1696254055431&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[Service]

package com.group.libraryapp.service.book;

import com.group.libraryapp.domain.book.Book;
import com.group.libraryapp.domain.user.BookRepository;
import com.group.libraryapp.dto.book.request.BookCreateRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class BookService {
    private final BookRepository bookRepository;

    // 생성자를 만들어 Spring bean을 주입받는다.
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @Transactional
    public void saveBook(BookCreateRequest request) {
        bookRepository.save(new Book(request.getName()));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/235&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.08.04 - [Spring] - #7 DTO와 VO(Entity는 링크한 글을 보자)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1696252540107&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;#7 DTO와 VO(Entity는 링크한 글을 보자)&quot; data-og-description=&quot;DTO : 데이터 전달용 객체 / VO : 값 표현용 객체 DTO VO 용도 레이어 간 데이터 전달 값 그 자체 표현 동등 결정 속성값이 모두 같아도 동일한 객체 X 속성값이 모두 같으면 동일 객체 가변 / 불변 sette&quot; data-og-host=&quot;radderveloper.tistory.com&quot; data-og-source-url=&quot;https://radderveloper.tistory.com/235&quot; data-og-url=&quot;https://radderveloper.tistory.com/235&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bupCn0/hyT5XULwAL/LapjfDdzq3QOYShJuW2ork/img.png?width=800&amp;amp;height=279&amp;amp;face=0_0_800_279,https://scrap.kakaocdn.net/dn/bZXmjs/hyT5V3IcST/VkWRRVQkYJdbOt5Xm2BNyK/img.png?width=800&amp;amp;height=279&amp;amp;face=0_0_800_279,https://scrap.kakaocdn.net/dn/qeGeI/hyT5XNYFE5/ksT9DCUcLnk4Z0EymWbD4K/img.png?width=1035&amp;amp;height=362&amp;amp;face=0_0_1035_362&quot;&gt;&lt;a href=&quot;https://radderveloper.tistory.com/235&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://radderveloper.tistory.com/235&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bupCn0/hyT5XULwAL/LapjfDdzq3QOYShJuW2ork/img.png?width=800&amp;amp;height=279&amp;amp;face=0_0_800_279,https://scrap.kakaocdn.net/dn/bZXmjs/hyT5V3IcST/VkWRRVQkYJdbOt5Xm2BNyK/img.png?width=800&amp;amp;height=279&amp;amp;face=0_0_800_279,https://scrap.kakaocdn.net/dn/qeGeI/hyT5XNYFE5/ksT9DCUcLnk4Z0EymWbD4K/img.png?width=1035&amp;amp;height=362&amp;amp;face=0_0_1035_362');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;#7 DTO와 VO(Entity는 링크한 글을 보자)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;DTO : 데이터 전달용 객체 / VO : 값 표현용 객체 DTO VO 용도 레이어 간 데이터 전달 값 그 자체 표현 동등 결정 속성값이 모두 같아도 동일한 객체 X 속성값이 모두 같으면 동일 객체 가변 / 불변 sette&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;radderveloper.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;● 테스트&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSBK35/btswkniPMfH/zVOKaaNVKNmCL64a4Ps9r0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSBK35/btswkniPMfH/zVOKaaNVKNmCL64a4Ps9r0/img.png&quot; data-origin-width=&quot;1165&quot; data-origin-height=&quot;563&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.0045%; margin-right: 10px;&quot; data-widthpercent=&quot;51.6&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSBK35/btswkniPMfH/zVOKaaNVKNmCL64a4Ps9r0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSBK35%2FbtswkniPMfH%2FzVOKaaNVKNmCL64a4Ps9r0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1165&quot; height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1UdHm/btsv9Ou2lSA/tSdNEI5qqiSgI6OeCboFaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1UdHm/btsv9Ou2lSA/tSdNEI5qqiSgI6OeCboFaK/img.png&quot; data-origin-width=&quot;392&quot; data-origin-height=&quot;202&quot; data-is-animation=&quot;false&quot; style=&quot;width: 47.8327%;&quot; data-widthpercent=&quot;48.4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1UdHm/btsv9Ou2lSA/tSdNEI5qqiSgI6OeCboFaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1UdHm%2Fbtsv9Ou2lSA%2FtSdNEI5qqiSgI6OeCboFaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;392&quot; height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hz6vk/btswcLj3vh2/66z5AhkHMTn58vRVLFfDB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hz6vk/btswcLj3vh2/66z5AhkHMTn58vRVLFfDB1/img.png&quot; data-alt=&quot;인텔리제이 콘솔에는 이렇게 찍혔다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hz6vk/btswcLj3vh2/66z5AhkHMTn58vRVLFfDB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHz6vk%2FbtswcLj3vh2%2F66z5AhkHMTn58vRVLFfDB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;914&quot; height=&quot;334&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;인텔리제이 콘솔에는 이렇게 찍혔다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Backend/Spring</category>
      <category>insert</category>
      <category>jpa</category>
      <category>spring</category>
      <category>SpringBoot</category>
      <author>RadderNepa</author>
      <guid isPermaLink="true">https://radderveloper.tistory.com/263</guid>
      <comments>https://radderveloper.tistory.com/263#entry263comment</comments>
      <pubDate>Mon, 2 Oct 2023 22:45:11 +0900</pubDate>
    </item>
  </channel>
</rss>