<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>작은 기록공간</title>
    <link>https://jhss9747.tistory.com/</link>
    <description>공부한 내용이나 잡다한걸 기록하는 공간</description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 16:55:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jhss9747</managingEditor>
    <image>
      <title>작은 기록공간</title>
      <url>https://tistory1.daumcdn.net/tistory/7498197/attach/fe889e9226754c35852c61080149d1f0</url>
      <link>https://jhss9747.tistory.com</link>
    </image>
    <item>
      <title>프로그래머스 | 의상</title>
      <link>https://jhss9747.tistory.com/63</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42578&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42578&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1773313922193&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42578&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/x4zXt/dJMb8RRQkgq/30mzk2Svj9cPv8AblqyJ00/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/JXNBn/dJMb8U8R3Ez/n9d0D9sDpzfcPZscLJv821/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42578&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42578&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/x4zXt/dJMb8RRQkgq/30mzk2Svj9cPv8AblqyJ00/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/JXNBn/dJMb8U8R3Ez/n9d0D9sDpzfcPZscLJv821/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;문제 설명&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;clothes의 각 행이 [의상 이름, 의상 종류]로 주어질 때, &lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;의상의 종류가 겹치지 않게 입을수 있는 경우의 수 구하기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;단, 의상의 이름이 겹치는 경우는 없다.&lt;/span&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;먼저 의상의 종류가 겹치지 않고, 입을수 있는 경우의 수만 구하는 것 이라면 의상의 이름은 중요치 않다.&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;[종류 : 개수] 이러한 꼴로 분류를 하면 될 것 같다.&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;입출력 예 1번을 확인해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[headgear : 2] , [eyewear : 1] 로 해시맵을 작성 할 수 있다.&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;1. 모두 1번씩은 입을수 있다 -&amp;gt; 2 + 1 = 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 중복되지 않은 옷끼리 한번씩 더 입을수 있다 -&amp;gt; 2 * 1 = 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 이를 모두 합하면 3+2 = 5 가 되므로 정답은 5이다.&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 data-ke-size=&quot;size16&quot;&gt;또한, 만약 예제 2번처럼 종류가 1개 밖에 없다면 어떻게 처리할 것인가에 대해서도 생각해야한다.&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;첫번째 예제를 예로 들면 이러한 꼴이 된다.&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;headgear = [off,on,on]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;eyewear = [off,on]&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;off는 모두 벗는것을 의미하고 on은 그것 하나만 입는것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 어느 한부위라도 무조건 입고 있어야 하므로 -1을 해줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 (n+1) * (m+1) -1 이라는 식이 나오게 된다.&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;이것을 java로 구현해보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1773314761393&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(String[][] clothes) {
        int answer = 0;
        String temp = &quot;&quot;;
        HashMap&amp;lt;String,Integer&amp;gt; hash = new HashMap&amp;lt;&amp;gt;();
        
        // 1. 옷의 종류별로 분류한다.
        for(int i = 0; i &amp;lt; clothes.length;i++){
            temp = clothes[i][1];
            hash.put(temp,hash.getOrDefault(temp,0)+1);
        }
        
        // 2. 만약 의상 종류가 한개밖에 없다면 해당 의상의 개수를 반환한다.
        if (hash.size() == 1) {
            answer = clothes.length;
        } else {
        // 3. 두개 이상이면 반복문을 실행하여 value값을 가져온다.
            for(Integer value : hash.values()){
                if (answer == 0){
                	// 초기값 할당
                    answer = value + 1;
                }else{
                	// value값에 1을 더하고 곱한 값을 할당
                    answer *= (value + 1);
                }
            }
            // 최종 결과에서 -1
            answer -= 1;
        }
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코테</category>
      <category>Java</category>
      <category>코테</category>
      <category>프로그래머스</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/63</guid>
      <comments>https://jhss9747.tistory.com/63#entry63comment</comments>
      <pubDate>Thu, 12 Mar 2026 20:47:24 +0900</pubDate>
    </item>
    <item>
      <title>샤오미 미 스틱 (Xiaomi TV Stick 4K) ADB 공장초기화</title>
      <link>https://jhss9747.tistory.com/61</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 미 스틱을 어쩌다가 받게 되었는데 비밀번호가 걸려있어서 사용하지를 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 인터넷을 찾아보니 리모컨의 OK버튼과 뒤로가기 버튼을 누르면서 부팅하면 공장초기화가 가능하다고 하여서 시도해보았지만 번번히 실패하고 포기하려던 찰나 ADB를 활용해서 초기화 할 수 있음을 알게되었다.&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;/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;a href=&quot;https://youtu.be/5renoEqjxqc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/5renoEqjxqc&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=5renoEqjxqc&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/biZuc8/hyZM9C6mGB/owPabK6ktqU4xNQWCd2a5k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/bsP2QE/hyZM6l31Aa/mtAm1yDpndNH4HkYFLeRek/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Xiaomi MDZ-27-AA висит на заставке, сброс до заводских настроек с помощью ком&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/5renoEqjxqc&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. ADB를 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-1. ADB는 &lt;a href=&quot;https://developer.android.com/tools/releases/platform-tools?hl=ko&quot;&gt;SDK 플랫폼 도구 출시 노트 &amp;nbsp;|&amp;nbsp; Android Studio &amp;nbsp;|&amp;nbsp; Android Developers&lt;/a&gt; 에 들어가서 다운한다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;741&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DMqiS/dJMcaiuSfau/dZhs2VYcAZEuldHHawUqoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DMqiS/dJMcaiuSfau/dZhs2VYcAZEuldHHawUqoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DMqiS/dJMcaiuSfau/dZhs2VYcAZEuldHHawUqoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDMqiS%2FdJMcaiuSfau%2FdZhs2VYcAZEuldHHawUqoK%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;977&quot; height=&quot;741&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;741&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-2. 압축을 풀고나온 platform-tools의 내용들을 모두 복사하고 C드라이브에 ADB 폴더를 만들어서 붙여넣는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blebj0/dJMcaiVWBDS/i4q4hCbwKIVr9TfMgNPjxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blebj0/dJMcaiVWBDS/i4q4hCbwKIVr9TfMgNPjxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blebj0/dJMcaiVWBDS/i4q4hCbwKIVr9TfMgNPjxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblebj0%2FdJMcaiVWBDS%2Fi4q4hCbwKIVr9TfMgNPjxK%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;968&quot; height=&quot;527&quot; data-origin-width=&quot;968&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;1-3. windows 키를 눌러서 '시스템 환경 변수 편집' 에 들어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EiB79/dJMcaeeWgGy/5ruxebSkQK2JOi0DgifnNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EiB79/dJMcaeeWgGy/5ruxebSkQK2JOi0DgifnNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EiB79/dJMcaeeWgGy/5ruxebSkQK2JOi0DgifnNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEiB79%2FdJMcaeeWgGy%2F5ruxebSkQK2JOi0DgifnNK%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;459&quot; height=&quot;258&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;258&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;1-4. 환경변수 -&amp;gt; 시스템 변수 내의 Path 더블클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D5NBz/dJMcaiuSfd9/d4DnnpEtXuxp3MLmYXur20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D5NBz/dJMcaiuSfd9/d4DnnpEtXuxp3MLmYXur20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D5NBz/dJMcaiuSfd9/d4DnnpEtXuxp3MLmYXur20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD5NBz%2FdJMcaiuSfd9%2Fd4DnnpEtXuxp3MLmYXur20%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;932&quot; height=&quot;540&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;540&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;1-5. 아까 파일을 옮겨 놓았던 C:\adb 로 경로 지정해서 추가&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lISXS/dJMcajgfmST/Sq6C8uvQtlCT9AI3KR3Jh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lISXS/dJMcajgfmST/Sq6C8uvQtlCT9AI3KR3Jh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lISXS/dJMcajgfmST/Sq6C8uvQtlCT9AI3KR3Jh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlISXS%2FdJMcajgfmST%2FSq6C8uvQtlCT9AI3KR3Jh1%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;524&quot; height=&quot;496&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 안드로이드 드라이버 다운로드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/studio/run/win-usb?hl=ko&quot;&gt;Google USB 드라이버 가져오기 &amp;nbsp;|&amp;nbsp; Android Studio &amp;nbsp;|&amp;nbsp; Android Developers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdeUN6/dJMcaap4wYU/vagVItlOb0syqJJK6DcBfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdeUN6/dJMcaap4wYU/vagVItlOb0syqJJK6DcBfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdeUN6/dJMcaap4wYU/vagVItlOb0syqJJK6DcBfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdeUN6%2FdJMcaap4wYU%2FvagVItlOb0syqJJK6DcBfK%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;917&quot; height=&quot;570&quot; data-origin-width=&quot;917&quot; data-origin-height=&quot;570&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C0Igt/dJMcai2H9MN/AXqI7P6WCo5Gk8LcXErJqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C0Igt/dJMcai2H9MN/AXqI7P6WCo5Gk8LcXErJqk/img.png&quot; data-alt=&quot;장치 관리자 검색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C0Igt/dJMcai2H9MN/AXqI7P6WCo5Gk8LcXErJqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC0Igt%2FdJMcai2H9MN%2FAXqI7P6WCo5Gk8LcXErJqk%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;353&quot; height=&quot;227&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;장치 관리자 검색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfPQiI/dJMcahJu7kr/7ZnC5oNmKvvbjn0N9l3SL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfPQiI/dJMcahJu7kr/7ZnC5oNmKvvbjn0N9l3SL0/img.png&quot; data-alt=&quot;드라이버 추가 버튼 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfPQiI/dJMcahJu7kr/7ZnC5oNmKvvbjn0N9l3SL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfPQiI%2FdJMcahJu7kr%2F7ZnC5oNmKvvbjn0N9l3SL0%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;589&quot; height=&quot;259&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;259&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbOPEB/dJMcagw3BXu/xSw6dEo2FmrWiY7bYWRcg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbOPEB/dJMcagw3BXu/xSw6dEo2FmrWiY7bYWRcg1/img.png&quot; data-alt=&quot;아까 다운받은 위치를 지정하여 드라이버 설치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbOPEB/dJMcagw3BXu/xSw6dEo2FmrWiY7bYWRcg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbOPEB%2FdJMcagw3BXu%2FxSw6dEo2FmrWiY7bYWRcg1%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;607&quot; height=&quot;439&quot; data-origin-width=&quot;607&quot; data-origin-height=&quot;439&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. cmd를 관리자 권한으로 열어서 아래의 명령어를 입력&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1762499291849&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. fastboot reboot-bootloader (장치를 연결하기전에 실행)
2. fastboot flashing unlock
3. fastboot reboot
4. fastboot reboot-bootloader (장치를 분리하고 실행 후 다시 연결)
5. fastboot devices
6. fastboot set_active b (또는 fastboot set_active a)
7. fastboot reboot&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;번호와 괄호의 내용은 제외하고 fastboot reboot-bootloader 부분만 붙여넣어서 실행하면 됩니다.&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;/p&gt;</description>
      <category>자료실</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/61</guid>
      <comments>https://jhss9747.tistory.com/61#entry61comment</comments>
      <pubDate>Fri, 7 Nov 2025 16:22:29 +0900</pubDate>
    </item>
    <item>
      <title>[multiSnake] #1 구상과 기본 설계</title>
      <link>https://jhss9747.tistory.com/59</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;개요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트를 사용해보고 싶다. 새로운 기술을 배우고 싶다. 재미있는 게임을 만들어보고 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세가지의 생각이 합쳐져서 일단 만들어보자 라는 생각으로 시작하게 된 멀티 스네이크 게임 프로젝트.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기존 게임과의 차별점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 스네이크 게임은 모두 알다시피 사과를 먹을 때 마다 꼬리가 길어지는 뱀을 조종해서 최대한 많은 사과를 먹는 게임이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 내가 경험해본 스네이크 게임은 여러가지 방해물(벽) 이 있거나 무한루프(모서리 통과가능)같은 것 만 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 여기에 나는 멀티플레이를 추가하여 최종적으로는 1vs1 매치가 되는 스네이크 게임을 만들고 싶어졌다.&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;로그인 없이 간단하게 접속하여 친구들과 1대1 매칭으로 스네이크 게임을 즐길수있다. 정말 멋지지 않은가&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 시계를 먹으면 나의 뱀의 속도가 느려짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상대방에게 벽을 설치할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 폭탄으로 벽을 제거할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상대방의 사과 위치를 재설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;추가로 모바일도 지원하면 더 좋고 방을 생성해서 빠르게 대결한다던지 리더보드를 만들어서 싱글플레이 기록을 기록한다던지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러한 느낌으로다가 심심할때 친구들과 할만한 즐거운 게임을 만들어 보고 싶다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;기술 스택&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 프론트 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;React&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 백엔드 : node.js (사용예정)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- DB : mongoDB (사용예정)&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;여기에 추가로 외부 파일들은 최대한 넣지 않고 다양한 라이브러리를 이용해서 화면을 구성하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 효과음등은 Tone.js등을 이용해서 소리를 낸다던지.. 그런 방식으로 해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;배포에 대해서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포는 최대한 돈이 안드는 방향으로 하려고 하는데 그 부분에 대해서는 조금 더 생각해봐야 할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로는 GitAction을 사용한 배포를 고려하고있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현재 진행상황&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트를 사용해서 기본적인 게임 로직은 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Tone.js를 이용해서 효과음을 만들고 최종적으로는 일단 혼자서 할수있는 게임을 만드는게 목표다.&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;a href=&quot;https://github.com/MSP-31/multiSnake&quot;&gt;https://github.com/MSP-31/multiSnake&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1759127706008&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - MSP-31/multiSnake&quot; data-og-description=&quot;Contribute to MSP-31/multiSnake development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/MSP-31/multiSnake&quot; data-og-url=&quot;https://github.com/MSP-31/multiSnake&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/UbW5y/hyZKpdnjkW/2OCtFe6yAoVr9oUxph7K70/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236&quot;&gt;&lt;a href=&quot;https://github.com/MSP-31/multiSnake&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/MSP-31/multiSnake&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/UbW5y/hyZKpdnjkW/2OCtFe6yAoVr9oUxph7K70/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236');&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;GitHub - MSP-31/multiSnake&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to MSP-31/multiSnake development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/개발 일지</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/59</guid>
      <comments>https://jhss9747.tistory.com/59#entry59comment</comments>
      <pubDate>Mon, 29 Sep 2025 16:23:20 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] 동시성 속에서 무결성 지키기</title>
      <link>https://jhss9747.tistory.com/58</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트는 싱크라이프라는 회사의 과제로 나온 '&lt;u&gt;스터디룸 예약 시스템&lt;/u&gt;'을 주제로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 목표는 &lt;b&gt;'동시성 속에서 무결성 지키기'&lt;/b&gt; 로써 &lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;중첩 예약 및 시간 겹침 방지를 &lt;/span&gt;중점으로 뒀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;핵심 로직&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;PostgreSQL의 &lt;b&gt;tstzrange&amp;nbsp;타입&lt;/b&gt;과&amp;nbsp;&lt;b&gt;EXCLUDE&amp;nbsp;USING&amp;nbsp;gist&amp;nbsp;제약&lt;/b&gt;을&amp;nbsp;활용을 활용하여 중첩 예약 및 시간 겹침 방지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- GlobalExceptionHandler를 통한 예외 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Spring Security를 활용한 접근 권한 제어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;중첩 예약 및 시간 겹침 방지 구현&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이번 프로젝트의 가장 핵심이 되는 부분으로써 예약 시스템에는 반드시 들어가야하는 조건이다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;처음에는 이것을 자주 사용하던 Mysql이나 MariaDB등으로 해결하려고 했으나 그렇게 하면 로직이 쓸데없이 복잡해진다.&lt;/span&gt;&lt;/span&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: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;- 중첩 예약 방지를 위해 이미 예약된 방의 정보를 불러와 비교해야한다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;- 시간 겹침을 방지하기 위해서 불러온 정보에서 또 다시 시작시간과 끝 시간을 분리하여 대조해야한다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;└&amp;gt; 이러한 과정들은 성능을 저하시키고, 로직을 복잡하게 만들수 있다.&lt;/span&gt;&lt;/span&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: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;그래서 과제에 힌트로 주어진 가장 효율적인 방법으로 &lt;b&gt;PostgreSQL&lt;/b&gt;의 &lt;b&gt;tstzrange&amp;nbsp;타입&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;과&amp;nbsp;&lt;/span&gt;&lt;b&gt;EXCLUDE USING gist 제약&lt;/b&gt;을 활용하기로 하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;- tstzrange( timestamp with time zone )&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #001d35;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;시간의 범위를 저장하는 PostgreSQL 타입으로써 &lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;시작시간과 끝시간 쌍의 형태로 시간의 범위를 지정한다.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1758889974530&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[&quot;2025-09-21 06:40:57.954+09&quot;,&quot;2025-09-21 07:40:57.954+09&quot;)&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;- GiST Index( Generalized Search Tree )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 종류의 데이터와 검색 방법을 지원할 수 있도록 일반화된 구조의 인덱스로써 유연성과 확장성이 뛰어남&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 사용하는 이유는 특정 영역에 겹치는 (시간이 겹치는) 데이터만 분류하기 위해서 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;└&amp;gt; EXCLUDE USING gist: GiST 인덱스를 사용해서 겹침 금지 제약을 설정.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Spring JPA에서는 이 둘을 지원하지 않기에 조금 다른 방법을 사용하여 적용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 엔티티에서는 &lt;b&gt;@Column&lt;/b&gt; 어노테이션의 &lt;b&gt;columnDefinition&lt;/b&gt;를 활용하여 &lt;b&gt;tstzrange&lt;/b&gt;타입임을 명시해주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1758891219965&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// JPA에서는 tstzrange 타입을 지원하지 않기 때문에 String으로 처리
@Column(name = &quot;time_range&quot;, columnDefinition = &quot;tstzrange&quot;)
private String timeRange;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Spring에서는 String 타입으로 처리하되 실제 데이터 타입은 tstzrange가 된다.&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;이후 Repository에서 조회 및 저장을 할때는 &lt;b&gt;@Query&lt;/b&gt; 어노테이션을 사용하여 직접 SQL문을 작성해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, &lt;b&gt;nativeQuery = true&lt;/b&gt; 옵션을 붙여 실제 DB에서 사용되는 문법임을 명시했다.&lt;/p&gt;
&lt;pre id=&quot;code_1758891332974&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
     * 예약 시간 범위가 겹치는 모든 예약을 조회합니다.
     * PostgreSQL의 '&amp;amp;&amp;amp;' 연산자를 사용하여 time_range 컬럼과 입력된 범위(tstzrange) 간의 겹침 여부를 검사합니다.
     *
     * @param start 시작 시간
     * @param end   종료 시간
     * @return      예약 리스트 반환
     */
    @Query(value = &quot;&quot;&quot;
    SELECT * FROM reservation r
    WHERE r.time_range &amp;amp;&amp;amp; tstzrange(:startDate, :endDate)&quot;&quot;&quot;, nativeQuery = true)
    List&amp;lt;Reservation&amp;gt; findByTimeRange(@Param(&quot;startDate&quot;) ZonedDateTime start,
                                      @Param(&quot;endDate&quot;) ZonedDateTime end);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1758891477123&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; /**
     * 예약 정보를 저장합니다.
     * PostgreSQL의 tstzrange 타입으로 시간 범위를 저장하며, 문자열로 전달된 범위를 CAST하여 삽입합니다.
     * 이후 RETUNING * 을 통하여 Reservation 객체를 반환함
     *
     * @param userId    유저 ID
     * @param roomId    회의실 ID
     * @param timeRange timeRange 형식의 시간 범위
     * @return          예약 정보 반환
     */
    @Query(value = &quot;&quot;&quot;
    INSERT INTO reservation (user_id, rooms_id, time_range)
    VALUES (:userId, :reservationId, CAST(:timeRange AS tstzrange))
    RETURNING *
    &quot;&quot;&quot;, nativeQuery = true)
    Reservation saveReservationWithRange(
            @Param(&quot;userId&quot;) Long userId,
            @Param(&quot;reservationId&quot;) Long roomId,
            @Param(&quot;timeRange&quot;) String timeRange
    );&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;b&gt;중첩 예약 및 시간 겹침 방지 구현&lt;/b&gt;을 위하여 마찬가지로 테이블을 생성할 때, 조건을 붙이려고 했으나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA에서 해당 조건을 인식하지 못하여서 SQL 파일을 따로 분리하고, 그곳에 테이블 생성 및 제약조건 처리를 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1758891667038&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;-- GIST 인덱스 기능을 위해 확장 설치
CREATE EXTENSION IF NOT EXISTS btree_gist;

-- 테이블이 없으면 생성
CREATE TABLE IF NOT EXISTS reservation (
  id SERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL,
  rooms_id BIGINT NOT NULL,
  time_range tstzrange NOT NULL
);

-- JPA에서는 해당 제약 조건을 처리하지 못하기 때문에 SQL문으로 따로 처리
ALTER TABLE reservation
ADD EXCLUDE USING gist (
  rooms_id WITH =,
  time_range WITH &amp;amp;&amp;amp;
);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CREATE EXTENSION IF NOT EXISTS btree_gist;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL에서 데이터베이스에서 Gist 인덱스의 기능을 확장하기 위해 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gist를 &lt;b&gt;B-tree&lt;/b&gt;처럼 일반적인 데이터 타입(숫자, 문자열, 날짜 등)에도 사용할 수 있도록 기능을 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;u&gt;&lt;b&gt;EXCLUDE 제약 조건을 정의&lt;/b&gt;&lt;/u&gt;하기 위해서 사용되었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 SQL 파일은 프로젝트가 실행되고 엔티티로 테이블이 생성되기 전에 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 reservation 테이블이 아직 생성되지 않았는데 제약 조건을 걸어버리는 문제가 생겨 여기서 테이블을 한번 더 정의하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후, &lt;b&gt;EXCLUDE USING gist&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 제약조건을 걸어서&amp;nbsp; &lt;b&gt;중첩 예약 및 시간 겹침&lt;/b&gt;을 방지하였다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 프로젝트는 아래에서 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 코드에 주석을 달아놨기에 이해하는데는 큰 무리가 없을것이다.&lt;/p&gt;
&lt;figure id=&quot;og_1758881744791&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - MSP-31/studyroom&quot; data-og-description=&quot;Contribute to MSP-31/studyroom development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/MSP-31/studyroom&quot; data-og-url=&quot;https://github.com/MSP-31/studyroom&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cy2eLn/hyZJ2wEb6p/aeWLB2TkupbVKqUkmReCh1/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236,https://scrap.kakaocdn.net/dn/bmHbti/hyZJS1Q1YW/Tr3c5wnvHLOoMESfNbhsBK/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236&quot;&gt;&lt;a href=&quot;https://github.com/MSP-31/studyroom&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/MSP-31/studyroom&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cy2eLn/hyZJ2wEb6p/aeWLB2TkupbVKqUkmReCh1/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236,https://scrap.kakaocdn.net/dn/bmHbti/hyZJS1Q1YW/Tr3c5wnvHLOoMESfNbhsBK/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_148_1056_236');&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;GitHub - MSP-31/studyroom&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to MSP-31/studyroom development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/개발 일지</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/58</guid>
      <comments>https://jhss9747.tistory.com/58#entry58comment</comments>
      <pubDate>Fri, 26 Sep 2025 22:11:08 +0900</pubDate>
    </item>
    <item>
      <title>[꿈찾아] 강의 문의 기획</title>
      <link>https://jhss9747.tistory.com/57</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;1.&amp;nbsp;유저의&amp;nbsp;정보는&amp;nbsp;최소한으로&amp;nbsp;받되,&amp;nbsp;DB에&amp;nbsp;기록을&amp;nbsp;남기지&amp;nbsp;말아야함 &lt;br /&gt;2.&amp;nbsp;필요한&amp;nbsp;유저&amp;nbsp;정보는&amp;nbsp;아래와&amp;nbsp;같다 &lt;br /&gt;&amp;nbsp;- 전화번호&lt;br /&gt;&amp;nbsp;-&amp;nbsp;이메일&amp;nbsp;주소 &lt;br /&gt;3.&amp;nbsp;유저는&amp;nbsp;자신이&amp;nbsp;보낸&amp;nbsp;문의가&amp;nbsp;언제&amp;nbsp;어떤내용으로&amp;nbsp;조회가&amp;nbsp;가능해야한다. &lt;br /&gt;4.&amp;nbsp;반복적인&amp;nbsp;요청을&amp;nbsp;보내는&amp;nbsp;악성&amp;nbsp;유저를&amp;nbsp;차단해야한다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;방안&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;회원가입이&amp;nbsp;필요없이&amp;nbsp;필드&amp;nbsp;폼을&amp;nbsp;만든다&amp;nbsp;그리고&amp;nbsp;그&amp;nbsp;안에는&amp;nbsp;아래의&amp;nbsp;내용들이&amp;nbsp;순서대로&amp;nbsp;들어간다. &lt;br /&gt;&amp;nbsp;-&amp;nbsp;회원의&amp;nbsp;이메일&amp;nbsp;주소 &lt;br /&gt;&amp;nbsp;-&amp;nbsp;회원이&amp;nbsp;연락받을&amp;nbsp;전화번호 &lt;br /&gt;&amp;nbsp;-&amp;nbsp;강의&amp;nbsp;요청하는&amp;nbsp;내용 &lt;br /&gt;&amp;nbsp;- (로봇확인)&lt;br /&gt;&lt;b&gt;&lt;/b&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;워크플로우&lt;/b&gt;&lt;br /&gt;-&amp;gt; 유저 &lt;br /&gt;&amp;nbsp;&amp;nbsp;1.&amp;nbsp;유저는&amp;nbsp;강의문의&amp;nbsp;페이지에&amp;nbsp;접속하여&amp;nbsp;필드폼을&amp;nbsp;채워&amp;nbsp;제출을&amp;nbsp;누른다. &lt;br /&gt;&amp;nbsp;&amp;nbsp;2.&amp;nbsp;서버에서는&amp;nbsp;제출된&amp;nbsp;폼을&amp;nbsp;미리&amp;nbsp;정의된&amp;nbsp;이메일로&amp;nbsp;전송한다&amp;nbsp;-&amp;gt;&amp;nbsp;관리자에게로 &lt;br /&gt;&amp;nbsp;&amp;nbsp;3.&amp;nbsp;유저가&amp;nbsp;입력한&amp;nbsp;이메일&amp;nbsp;주소로&amp;nbsp;유저가&amp;nbsp;전송한&amp;nbsp;문의&amp;nbsp;내역을&amp;nbsp;정리해서&amp;nbsp;다시금&amp;nbsp;보내준다. &lt;br /&gt;&lt;br /&gt;-&amp;gt; 관리자 &lt;br /&gt;&amp;nbsp;&amp;nbsp;1.&amp;nbsp;관리자는&amp;nbsp;유저가&amp;nbsp;전송한&amp;nbsp;문의&amp;nbsp;내역을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다. &lt;br /&gt;&amp;nbsp;&amp;nbsp;2.&amp;nbsp;이후에&amp;nbsp;관리자는&amp;nbsp;해당&amp;nbsp;메일에&amp;nbsp;적힌&amp;nbsp;전화번호&amp;nbsp;또는&amp;nbsp;이메일로&amp;nbsp;회신하며&amp;nbsp;소통한다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;장점&lt;/b&gt; &lt;br /&gt;-&amp;nbsp;사이트에서는&amp;nbsp;유저와&amp;nbsp;관리자간의&amp;nbsp;소통을&amp;nbsp;중개만&amp;nbsp;하기에&amp;nbsp;개인정보&amp;nbsp;유출등의&amp;nbsp;보안적인&amp;nbsp;측면에서&amp;nbsp;유리하다. &lt;br /&gt;-&amp;nbsp;백엔드에&amp;nbsp;불필요한&amp;nbsp;계정&amp;nbsp;정보를&amp;nbsp;남기지&amp;nbsp;않기에&amp;nbsp;보안적으로&amp;nbsp;유리하다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt; &lt;br /&gt;-&amp;nbsp;유저는&amp;nbsp;문의내역을&amp;nbsp;확인하기&amp;nbsp;위해서&amp;nbsp;자신이&amp;nbsp;이용하는&amp;nbsp;메일&amp;nbsp;서비스를&amp;nbsp;통해&amp;nbsp;열람해야한다 &lt;br /&gt;&amp;nbsp;-&amp;gt;&amp;nbsp;오히려&amp;nbsp;한곳에서&amp;nbsp;모두&amp;nbsp;확인가능하고&amp;nbsp;이후의&amp;nbsp;문의는&amp;nbsp;사이트를&amp;nbsp;통해&amp;nbsp;접속하지&amp;nbsp;않아도&amp;nbsp;되기에&amp;nbsp;편리하다. &lt;br /&gt;&lt;br /&gt;추가사항 &lt;br /&gt;- 플로팅 버튼에 해당 강의 문의 버튼을 집어넣어서 접근성을 향상시켜야한다.&lt;/p&gt;</description>
      <category>프로그래밍/개발 일지</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/57</guid>
      <comments>https://jhss9747.tistory.com/57#entry57comment</comments>
      <pubDate>Fri, 12 Sep 2025 17:36:50 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Boot] 검색 기능 구현</title>
      <link>https://jhss9747.tistory.com/55</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스프링에서 검색기능을 구현하는데에는 여러가지 방법이 있지만 나는 그 중 2가지 방법을 소개하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. @query&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필터링할 항목이 적을때는 간단하게 @query 어노테이션을 사용해서 처리할 수 있다.&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_1750313211210&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 해당 팀의 리더 여부 확인
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return Boolean
 */
@Query(&quot;SELECT tu.isLeader &quot; +
        &quot;FROM TeamUser tu &quot; +
        &quot;JOIN User u ON tu.user.no = u.no &quot; +
        &quot;WHERE tu.team.no = :teamNo AND u.no = :userNo&quot;)
Boolean isLeader(@Param(&quot;teamNo&quot;) Long teamNo, @Param(&quot;userNo&quot;) Long userNo);&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;@Query로 sql 쿼리문을 작성해서 비교하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에는 해당 쿼리문에 들어갈 인자값을 @Param 으로 넘겨주고 결과를 반환한다.&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;여기 이 코드에서는 TeamUser테이블과 User 테이블을 유저 번호로 조인하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TeamUser에 있는 teamNo로 같은 팀을 찾고, userNo로 해당 유저의 정보를 조회한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 테이블의 isLeader를 찾아 반환하는 코드이다.&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;이런식으로 조금더 상세하게 조회를 해야한다면 @Query 어노테이션을 사용하기도 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1750313544421&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 모든 팀 정보 조회
 * @param userNo (필터) 유저번호
 * @param pageable 페이징 크기
 * @return TeamSearchDto
 */
@Query(&quot;SELECT new com.beyond.backend.domain.team.dto.TeamResponseDto&quot; +
        &quot;(t.no, t.teamName, t.teamIntroduce, t.projectStatus) &quot; +
        &quot;FROM Team t &quot; +
        &quot;JOIN TeamUser tu ON t.no = tu.team.no &quot; +
        &quot;WHERE (:userNo IS NULL OR tu.user.no = :userNo) &quot; +
        &quot;AND (:teamName IS NULL OR t.teamName LIKE %:teamName%) &quot; +
        &quot;AND (:teamIntroduce IS NULL OR t.teamIntroduce LIKE %:teamIntroduce%) &quot; +
        &quot;AND (:projectStatus IS NULL OR t.projectStatus = :projectStatus) &quot; +
        &quot;GROUP BY t.no&quot;)
Page&amp;lt;TeamResponseDto&amp;gt; findByUserNoForUserTeams(
        @Param(&quot;userNo&quot;) Long userNo,
        @Param(&quot;teamName&quot;) String teamName,
        @Param(&quot;teamIntroduce&quot;) String teamIntroduce,
        @Param(&quot;projectStatus&quot;) ProjectStatus projectStatus,
        Pageable pageable);&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Page를 사용하여 페이징 처리를 하였고, 인자값을 받아오되 만약 값이 Null 이라면 (빈 값이라면)&amp;nbsp; 해당 조건은 건너띈다.&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;이렇게 많은 양의 조건을 붙여야하는 복잡한 동적 쿼리문을 처리하기엔 비효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;2. &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;Querydsl&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Querydsl은 타입 안전한(Type-Safe) 쿼리를 생성할 수 있도록 도와주는 오픈 소스 프레임워크로서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 코드를 이용해서 데이터베이스 쿼리 (SQL, JPQL 등)를 작성할 수 있게 해주는 &quot;빌더&quot; 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;쉽게 말해, 우리가 보통 SQL이나 JPQL 쿼리를 문자열로 작성하는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문자열 쿼리는 오타가 나거나 필드명이 바뀌어도 컴파일 시점에는 오류를 알 수 없고 런타임에 가서야 오류가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Querydsl은 이런 문제점을 해결하기 위해 나왔다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Querydsl의 주요 특징 및 장점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 타입 안전성 (Type-Safety)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 큰 장점으로서 Querydsl은 컴파일 시점에 엔티티(Entity)를 기반으로 Q-Class라는 것을 자동으로 생성합니다. 이 Q-Class는 엔티티의 필드들을 정적인 타입으로 가지고 있어서, 쿼리를 작성할 때 오타나 잘못된 필드명을 사용하면 컴파일 에러가 발생합니다.&lt;/li&gt;
&lt;li&gt;이는 런타임 오류를 줄여주고 개발 생산성을 크게 향상시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 직관적인 쿼리 작성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 쿼리 대신 자바 코드로&amp;nbsp; 쿼리를 작성하므로 IDE의 자동완성 기능을 활용 가능하다.&lt;/li&gt;
&lt;li&gt;SQL이나 JPQL과 유사한 문법으로 &lt;a href=&quot;https://adjh54.tistory.com/440&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;메서드 체이닝 방식&lt;/a&gt;을 사용하여 쿼리를 구성하기에 가독성이 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3 .동적 쿼리 (Dynamic Query) 생성 용이&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;where() 절 등에 조건을 유연하게 추가하여 조건에 따라 쿼리 내용이 달라지는 동적 쿼리 작성이 매우 편리하다.&lt;/li&gt;
&lt;li&gt;예를 들어서, 검색 조건이 있을 때만 특정 AND 조건을 추가하는 등의 로직을 깔끔하게 구현 가능 하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4 . 다양한 백엔드 지원&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA, JDBC, SQL, MongoDB 등 다양한 데이터 베이스 및 데이터 소스 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 프로젝션 (Projection) 기능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리 결과를 특정 DTO로 바로 매핑하여 가져올 수 있는 기능을 지원한다.&lt;/li&gt;
&lt;li&gt;이를 통해 엔티티 전체를 가져오지 않고 필요한 데이터만 선택적으로 가져올 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Querydsl의&amp;nbsp;동작&amp;nbsp;방식&amp;nbsp;(JPA&amp;nbsp;기준)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. Q-Class 생성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Querydsl을&amp;nbsp;사용하기&amp;nbsp;위해&amp;nbsp;빌드&amp;nbsp;도구&amp;nbsp;(Gradle,&amp;nbsp;Maven)에&amp;nbsp;설정을&amp;nbsp;추가하면,&amp;nbsp;컴파일&amp;nbsp;시점에&amp;nbsp;엔티티&amp;nbsp;클래스(예:&amp;nbsp;Member.java)를&amp;nbsp;분석하여&amp;nbsp;해당&amp;nbsp;엔티티에&amp;nbsp;대한&amp;nbsp;Q-Class&amp;nbsp;(예:&amp;nbsp;QMember.java)를&amp;nbsp;자동으로&amp;nbsp;생성합니다. &lt;br /&gt;이 Q-Class는 엔티티 필드에 해당하는 정적인 필드들을 가지고 있습니다. (예: QMember.member.name, QMember.member.age).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. JPAQueryFactory를&amp;nbsp;이용한&amp;nbsp;쿼리&amp;nbsp;작성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPAQueryFactory라는&amp;nbsp;객체를&amp;nbsp;생성하여&amp;nbsp;Querydsl&amp;nbsp;쿼리를&amp;nbsp;시작합니다. &lt;br /&gt;이&amp;nbsp;팩토리를&amp;nbsp;통해&amp;nbsp;Q-Class를&amp;nbsp;사용하여&amp;nbsp;select,&amp;nbsp;from,&amp;nbsp;where,&amp;nbsp;join,&amp;nbsp;orderBy&amp;nbsp;등&amp;nbsp;SQL과&amp;nbsp;유사한&amp;nbsp;메서드를&amp;nbsp;체인&amp;nbsp;방식으로&amp;nbsp;호출하여&amp;nbsp;쿼리를&amp;nbsp;구성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 쿼리 실행&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fetch(),&amp;nbsp;fetchOne(),&amp;nbsp;fetchResults()&amp;nbsp;(deprecated),&amp;nbsp;fetchCount()&amp;nbsp;(deprecated)&amp;nbsp;등의&amp;nbsp;메서드를&amp;nbsp;호출하여&amp;nbsp;구성된&amp;nbsp;쿼리를&amp;nbsp;실행하고&amp;nbsp;결과를&amp;nbsp;반환받습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;간단한 예시 코드&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 사용자가 주문한 상품만 보여주는 페이지에 검색기능과 관리자 여부를 판단해야 하는 코드가 있다고 생각해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 경우 Querydsl은 이렇게 코드를 작성할 수 있다.&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_1750316152215&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;...
import static com.beyond.homs.company.entity.QCompany.company;
import static com.beyond.homs.order.entity.QOrder.order;
import static com.beyond.homs.product.entity.QProduct.product;
import static com.beyond.homs.order.entity.QOrderItem.orderItem;
import static com.beyond.homs.user.entity.QUser.user;
import static com.beyond.homs.wms.entity.QDeliveryAddress.deliveryAddress;
import static com.beyond.homs.order.entity.QClaim.claim;
...

@Repository
@RequiredArgsConstructor
public class OrderItemRepositoryImpl implements OrderItemRepositoryCustom {
    // Querydsl 쿼리를 생성하는 핵심 클래스
    // 내부적으로 EntityManager를 사용하여 데이터베이스에 접근
    private final JPAQueryFactory queryFactory;

    // 별칭 충돌을 피하기 위해 새로운 QCompany 인스턴스 생성
    // deliveryAddress를 통한 company 조인에 사용할 별칭
    private final QCompany deliveryCompany = new QCompany(&quot;deliveryCompany&quot;); // 새로운 별칭

    // 동적 검색 조건 메서드
    private BooleanExpression searchOptions(String keyword, OrderSearchOption option) {
        if (option == OrderSearchOption.ORDER_CODE){
            return order.orderCode.contains(keyword); // 코드 검색
        } else if (option == OrderSearchOption.COMPANY_NAME){
            return company.companyName.contains(keyword); // 회사 검색
        }
        return null; // 일치하는 옵션 없으면 null
    }

    // 사용자 ID 기반 필터링 조건 추가
    private BooleanExpression userEq(Long userId) {
        if (userId == null) {
            return null; // userId가 null이면 모든 주문 조회 (관리자 케이스)
        }
        // 주문을 생성한 user의 ID와 userId가 일치하는 경우
        return order.user.userId.eq(userId);
    }

    // 관리자 역할에 따른 추가 필터링 조건
    private BooleanExpression adminSpecificFilter(boolean isAdmin) {
        if (isAdmin) {
            // 관리자일 경우 deliveryName과 dueDate가 모두 null인 주문은 보지 못하게 필터링
            return order.deliveryAddress.deliveryName.isNotNull().or(order.dueDate.isNotNull());
        }
        return null; // 관리자가 아니면 이 조건은 적용하지 않음
}&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;/p&gt;
&lt;pre id=&quot;code_1750316152218&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Override
public Page&amp;lt;OrderResponseDto&amp;gt; findOrders(OrderSearchOption option, String keyword, Long userId, boolean isAdmin, Pageable pageable) {
    List&amp;lt;OrderResponseDto&amp;gt; content = queryFactory // JPAQueryFactory 사용
            // select문 시작
            .select(Projections.constructor(OrderResponseDto.class, // DTO 인트턴스 직접 생성
                    order.orderId,
                    order.orderCode,
                    company.companyName,
                    deliveryAddress.deliveryName,
                    order.orderDate,
                    order.dueDate,
                    order.approved,
                    order.parentOrder.orderId,
                    order.rejectReason,
                    order.orderStatus
            ))
            .from(order)
            .leftJoin(order.user,user)
            .leftJoin(user.company,company)
            .leftJoin(deliveryAddress.company,deliveryCompany)
            .where(
                    searchOptions(keyword, option),  // 동적 검색 조건
                    userEq(userId) ,                 // 사용자 필터링 조건 추가
                    adminSpecificFilter(isAdmin)     // 관리자 필터링 조건 추가
            )
            .orderBy(order.orderDate.desc()) // 정렬
            .offset(pageable.getOffset()) // 페이징 시작 오프셋
            .limit(pageable.getPageSize()) // 페이지 크기
            .fetch(); // 실제 쿼리 실행 및 결과 리스트 반환

    // 총 개수 쿼리
    JPAQuery&amp;lt;Long&amp;gt; totalCount = queryFactory
            .select(order.count()) // COUNT 쿼리
            .from(order)
            .leftJoin(order.user,user)
            .leftJoin(user.company,company)
            .leftJoin(deliveryAddress.company,deliveryCompany)
            .where(
                    searchOptions(keyword, option),
                    userEq(userId),
                    adminSpecificFilter(isAdmin)     // 관리자 필터링 조건 추가
            );

    // Spring Data JPA의 PageableExecutionUtils를 사용하여 Page 객체 생성
    return PageableExecutionUtils.getPage(content,pageable,totalCount::fetchOne);
}&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드가 더 길어보이지만 가독성이나 유지보수 측면에서도 더 효율적이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;QuryDsl을 사용하기 전 설정해야 하는 것&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Querydsl을 사용하기 위해서는 먼저 여러가지 설정을 해줘야하는데, 여기서는 Gradle 기준으로 설명하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Q-Class를 생성해야하는데 이것을 생성하기 위해서는 build.gradle에 아래의 코드를 추가해야한다.&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;- HOMS 프로젝트에서 내가 쓴 방법&lt;/p&gt;
&lt;pre id=&quot;code_1750322492333&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

ext {
    querydslVersion = &quot;5.0.0&quot;
}

// ...

dependencies {
    // ...
    // --- Querydsl ---
    implementation &quot;com.querydsl:querydsl-jpa:${querydslVersion}:jakarta&quot;
    annotationProcessor &quot;com.querydsl:querydsl-apt:${querydslVersion}:jakarta&quot;
    annotationProcessor &quot;jakarta.annotation:jakarta.annotation-api&quot;
    annotationProcessor &quot;jakarta.persistence:jakarta.persistence-api&quot;
    // ...
}&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;- Gemini가 알려준 방법&lt;/p&gt;
&lt;pre id=&quot;code_1750322540282&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins {
    id &quot;com.ewerk.gradle.plugins.querydsl&quot; version &quot;1.0.10&quot; // &amp;lt;-- 이 플러그인
}

// ...

querydsl { // &amp;lt;-- 이 블록 (플러그인에 의해 제공됨)
    jpa = true 
    querydslSourcesDir = &quot;$buildDir/generated/querydsl&quot; 
}

sourceSets {
    main {
        java {
            srcDirs += [ &quot;$buildDir/generated/querydsl&quot; ] // &amp;lt;-- Q-Class 경로 추가
        }
    }
}&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;가장 큰 차이점은 Q-Class 생성을 위한 Gradle 플러그인의 유무이고 핵심은 annotationProcessor 이다.&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;Gradle의 annotationProcessor 설정은 컴파일 시점에 특정 어노테이션을 처리하고 코드를 생성하는 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Querydsl의 querydsl-apt 모듈은 바로 이러한 어노테이션 프로세서입니다.&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;내가 사용한 build.gradle에서는 com.ewerk.gradle.plugins.querydsl 플러그인을 명시적으로 사용하지 않았지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 직접 annotationProcessor에 Querydsl의 APT 모듈을 추가했다.&lt;/p&gt;
&lt;pre id=&quot;code_1750322738167&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;annotationProcessor &quot;com.querydsl:querydsl-apt:${querydslVersion}:jakarta&quot;&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;이것만으로도 Q-Class는 정상적으로 생성된다. 그 이유는 아래와 같다고 한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;querydsl-apt&amp;nbsp;모듈의&amp;nbsp;역할&lt;/b&gt;:&amp;nbsp;이&amp;nbsp;모듈&amp;nbsp;자체가&amp;nbsp;엔티티&amp;nbsp;클래스에&amp;nbsp;있는&amp;nbsp;@Entity&amp;nbsp;등의&amp;nbsp;어노테이션을&amp;nbsp;감지하고,&amp;nbsp;해당&amp;nbsp;엔티티에&amp;nbsp;대한&amp;nbsp;Q-Class를&amp;nbsp;자동으로&amp;nbsp;생성하는&amp;nbsp;로직을&amp;nbsp;포함하고&amp;nbsp;있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Gradle의&amp;nbsp;annotationProcessor&amp;nbsp;기본&amp;nbsp;동작&lt;/b&gt;:&amp;nbsp;Gradle은&amp;nbsp;annotationProcessor&amp;nbsp;설정에&amp;nbsp;포함된&amp;nbsp;라이브러리들을&amp;nbsp;빌드&amp;nbsp;시점에&amp;nbsp;어노테이션&amp;nbsp;프로세서로&amp;nbsp;실행합니다.&amp;nbsp;따라서&amp;nbsp;querydsl-apt가&amp;nbsp;실행되어&amp;nbsp;Q-Class를&amp;nbsp;생성하게&amp;nbsp;됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기본&amp;nbsp;출력&amp;nbsp;경로&lt;/b&gt;:&amp;nbsp;&lt;i&gt;querydsl-apt&lt;/i&gt;는&amp;nbsp;특정&amp;nbsp;Gradle&amp;nbsp;플러그인이&amp;nbsp;설정되어&amp;nbsp;있지&amp;nbsp;않으면,&amp;nbsp;기본적으로&amp;nbsp;Gradle의&amp;nbsp;빌드&amp;nbsp;경로(일반적으로&amp;nbsp;&lt;i&gt;build/generated/sources/annotationProcessor/java/main&lt;/i&gt;&amp;nbsp;또는&amp;nbsp;&lt;i&gt;build/generated/sources/annotationProcessor/java/main/&amp;lt;패키지&amp;nbsp;경로&amp;gt;&lt;/i&gt;)&amp;nbsp;아래에&amp;nbsp;Q-Class를&amp;nbsp;생성합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 플러그인을 사용하는 이유는 무엇일까&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;명시적인&amp;nbsp;Q-Class&amp;nbsp;경로&amp;nbsp;지정&lt;/b&gt;:&amp;nbsp;querydslSourcesDir을&amp;nbsp;통해&amp;nbsp;Q-Class가&amp;nbsp;생성될&amp;nbsp;정확한&amp;nbsp;디렉토리를&amp;nbsp;개발자가&amp;nbsp;직접&amp;nbsp;지정할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이는&amp;nbsp;빌드&amp;nbsp;스크립트의&amp;nbsp;가독성을&amp;nbsp;높이고,&amp;nbsp;Q-Class의&amp;nbsp;위치를&amp;nbsp;예측&amp;nbsp;가능하게&amp;nbsp;만듭니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;sourceSets&amp;nbsp;자동&amp;nbsp;추가&lt;/b&gt;:&amp;nbsp;Q-Class가&amp;nbsp;생성될&amp;nbsp;경로를&amp;nbsp;sourceSets.main.java.srcDirs에&amp;nbsp;자동으로&amp;nbsp;추가해줍니다.&amp;nbsp;이&amp;nbsp;플러그인을&amp;nbsp;사용하지&amp;nbsp;않으면&amp;nbsp;이&amp;nbsp;부분을&amp;nbsp;수동으로&amp;nbsp;추가해야&amp;nbsp;IDE에서&amp;nbsp;Q-Class를&amp;nbsp;소스&amp;nbsp;파일로&amp;nbsp;인식합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;clean&amp;nbsp;태스크&amp;nbsp;통합&lt;/b&gt;:&amp;nbsp;clean&amp;nbsp;태스크에&amp;nbsp;Q-Class&amp;nbsp;생성&amp;nbsp;디렉토리를&amp;nbsp;포함시켜&amp;nbsp;빌드&amp;nbsp;부산물을&amp;nbsp;깔끔하게&amp;nbsp;제거할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;도와줍니다. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;명확한&amp;nbsp;의도&lt;/b&gt;:&amp;nbsp;빌드&amp;nbsp;스크립트만&amp;nbsp;봐도&amp;nbsp;&quot;이&amp;nbsp;프로젝트는&amp;nbsp;Querydsl을&amp;nbsp;사용하고&amp;nbsp;Q-Class를&amp;nbsp;자동&amp;nbsp;생성한다&quot;는&amp;nbsp;의도를&amp;nbsp;명확하게&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있습니다.&lt;/li&gt;
&lt;/ol&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;이렇게 설정을 하고나면 Q-Class가 자동으로 생성이되고 커스텀 리포지토리를 생성해서 사용하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 검색 쿼리가 필요할때는 @Query 어노테이션을 사용하면 되고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 검색 쿼리가 필요할때는 QueryDsl을 사용하는것을 고려해보는게 좋을것 같다.&lt;/p&gt;</description>
      <category>프로그래밍/Spring Boot</category>
      <category>@Query</category>
      <category>querydsl</category>
      <category>spring</category>
      <category>springboot</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/55</guid>
      <comments>https://jhss9747.tistory.com/55#entry55comment</comments>
      <pubDate>Thu, 19 Jun 2025 17:55:33 +0900</pubDate>
    </item>
    <item>
      <title>한화시스템 BEYOND SW CAMP 마지막 회고</title>
      <link>https://jhss9747.tistory.com/54</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;최종 발표의 마무리.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6월 11일 최종프로젝트를 발표함과 동시에 교육 또한 끝났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 최종 프로젝트 때에는 9주동안 배운것을 모두 보여주는 자리였기에 정말 열심히 임했다.&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;우리팀은 주문관리 시스템을 주제로 B2B 주문관리시스템을 만들었었다&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-filename=&quot;Animation (2).gif&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;872&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD5WqG/btsOBsfhNh2/eJUifOGjFWAP6BjzGWzC80/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD5WqG/btsOBsfhNh2/eJUifOGjFWAP6BjzGWzC80/img.gif&quot; data-alt=&quot;최종 프로젝트때 만든 'HOMS' 로그인 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD5WqG/btsOBsfhNh2/eJUifOGjFWAP6BjzGWzC80/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dD5WqG/btsOBsfhNh2/eJUifOGjFWAP6BjzGWzC80/img.gif&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;701&quot; height=&quot;319&quot; data-filename=&quot;Animation (2).gif&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;872&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;최종 프로젝트때 만든 'HOMS' 로그인 화면&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;프로젝트를 진행하면서 가장 어렸웠던 점은 B2B 시스템에 대한 이해였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소에는 B2C 즉, 기업과 소비자간의 거래만 접해봤기에 기업과 기업간의 거래에 대한 경험이 없어 이를 구축하는데 애를 먹었다.&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;다양한 사례와 예시를 찾아보고 여러 경험담들을 들어보며 B2B 주문관리를 짚어보았는데&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;/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;/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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;피드백과 느낀점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로 발표에서의 심사평은 실제 기업에서 사용할만한 프로세스를 잘 구성하였지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관리자 측면에서 메인페이지의 대시보드 등을 봤을때 한눈에 중요 정보가 들어와야하는데 그런 부분이 미숙하다고 하셨고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;(차트 등에서 보여주는 정보의 중요도가 떨어진다)&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에 주문하는 부분과 상품 부분을 결합했으면 좋지 않았을까 등의 피드백이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비록 1등은 하지못했지만 B2B 거래에 대한 프로세스를 이해하는데 많은 도움이 되었고,&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;/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;/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;AWS S3를 도입하면서 보안을 위해 S3에 바로 연결하는게 아닌 백엔드를 거쳐서 데이터를 주고받게 하게 한다던지,&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마지막으로 부트캠프 후기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6개월이라는 짧으면 짧고 길면 긴 시간동안 많은 일이 있었고, 정말 고봉밥 처럼 꽉꽉눌러 배울 수 있는 시간이였다.&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;또한 항상 쓰던 순수 html을 버리고 vue를 써보는 등 더 다양한 도전도 해볼 수 있었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 기초부터 시작하므로써 이미 알고있던 내용은 더 확실하게, 이후에는 배웠던것을 활용해서 프로젝트를 해보고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로는 이전에 배웠던 내용들이 지금은 어떻게 개선이 되었는지 배우면서&lt;/p&gt;
&lt;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;물론 6개월이라는 시간안에 더 깊고 상세하게 배울순 없었지만 강사님이 그 부분도 캐치하시고 관련한 수업을 따로 마련하시거나,&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트는 총 4번인가 5번정도 진행하는데 각 프로젝트는 이전까지 배운 내용들을 실습하는 느낌에 가까웠고,&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;/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;/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;6개월동안 정말 많이 배웠고 얻어가는것도 많았다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다음 단계는 취업이다. 지금까지 배우고 쌓은걸 잘 정리해서 멋지게 마무리하고 싶다.&lt;/p&gt;</description>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/54</guid>
      <comments>https://jhss9747.tistory.com/54#entry54comment</comments>
      <pubDate>Fri, 13 Jun 2025 18:24:37 +0900</pubDate>
    </item>
    <item>
      <title>한화시스템 BEYOND SW CAMP 4월 4주차 회고</title>
      <link>https://jhss9747.tistory.com/53</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로젝트의 설계의 마무리 단계에 접어들다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주부터 계속 작업하던 요구사항 정의서나 기능명세서등을 정리하고 이제 화면설계와 ERD 설계에 들어갔다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 항상 가장 어려운것은 요구사항 정의나 기능명세, 화면 설계등이 아니라 ERD 설계가 가장 어려운 것 같다.&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;다른 부분들은 작업을 하면서 유동적으로 추가하거나 지울수 있지만 ERD는 그 특성상 그렇게 하기 힘들기 때문에 처음부터 되도록이면 수정할 부분이 없도록 작성을 하기 때문에 더욱 생각할 부분이 많은 것 같다.&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;모두 구현하는것은 고사하고 프로젝트를 완성할 수 있을지에 대한 걱정이 있다.&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;또한, 이번에 프로젝트 명이 HOMS로 정해졌다. 주제가 주문 관리 시스템이기 때문에 재치있는 이름이라고 생각한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다음주의 계획&lt;/h3&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다음주 수요일 이전까지 빠르게 ERD와 화면설계서를 마무리하고 개발환경을 세팅한 다음, 집에서 작업을 할 생각이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 5월 부터는 실제 개발에 들어가서 6월 이전까지 만족할만한 결과를 내놓는게 목표이다.&lt;/p&gt;</description>
      <category>회고록</category>
      <category>한화시스템 beyond sw camp</category>
      <category>회고록</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/53</guid>
      <comments>https://jhss9747.tistory.com/53#entry53comment</comments>
      <pubDate>Sun, 27 Apr 2025 15:15:52 +0900</pubDate>
    </item>
    <item>
      <title>한화시스템 BEYOND SW CAMP 4월 3주차 회고</title>
      <link>https://jhss9747.tistory.com/52</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;강의가 없는 한주의 시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 부터는 계속 강의는 없고 대신 모든 시간동안 최종 프로젝트에 집중하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해서 책상의 배치도 팀원들과 항상 회의할수 있도록 서로 마주보게 배치하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오전 9시부터 오후 5시 50분까지의가 없는 한주의 시작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주 부터는 계속 강의는 없고 대신 모든 시간동안 최종 프로젝트에 집중하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해서 책상의 배치도 팀원들과 항상 회의할수 있도록 서로 마주보게 배치하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최종 프로젝트의 틀을 잡다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 프로젝트의 대주제는 '주문관리 시스템' 으로 정하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 여기서 일반적인 프로젝트와 다른점은 B2B 주문관리 시스템을 구축하는것으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한화 솔루션 케미칼 부분에 대한 B2B 주문관리 시스템을 실제와 비슷하게 구축하는것을 목표로 하고있다.&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;기본적인 주문관리 시스템을 베이스로 해당 소재를 사용하는것 뿐이라고 생각한다.&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;사실 큰 차별점은 없고 조금 더 편리하게 채팅 기능등을 넣기로 하였다.&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;여태까지 이런 주제로 프로젝트를 진행한 조는 우리가 처음이라고도 했고, 좋은 소재지만 좀 지루할수도 있겠다 라고 하셨다.&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;다른 팀원들도 그렇게 생각하기에 이 주제 그대로 가져가기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회고를 마치며&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루에 대략 7~8시간 동안 계속 마주보고 회의를 하는데 쉽지가 않다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트도 잘 마무리하고 끝냈으면 좋겠다.&lt;/p&gt;</description>
      <category>회고록</category>
      <category>한화시스템 beyond sw camp</category>
      <category>회고록</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/52</guid>
      <comments>https://jhss9747.tistory.com/52#entry52comment</comments>
      <pubDate>Sun, 20 Apr 2025 23:56:58 +0900</pubDate>
    </item>
    <item>
      <title>한화시스템 BEYOND SW CAMP 4월 2주차 회고</title>
      <link>https://jhss9747.tistory.com/51</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;부트캠프 교육과정의 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주로 모든 교육과정이 끝났고, 이제 최종프로젝트와 3번째 팀 프로젝트만이 남았다.&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;/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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 세세하게 잘 알려주시긴 하지만 시간이 짧기때문에 개인적으로 복습하는 시간도 꼭 필요하다고 생각하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈틈없이 프로젝트를 진행하게 되어있어서 정말 열심히 참여한다면 그에맞는 지식을 얻어갈 수 있다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3번째 팀프로젝트의 마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번째 팀 프로젝트는 다음주 월요일에 바로 발표이므로 지금도 작업하고 준비중에 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2주동안 DevOps를 배움과 동시에 프로젝트도 같이 진행이 되어서 배우는 즉시 응용해서 프로젝트에 적용해야 했다.&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;배포를 Aws 같은 클라우드에 하려고 생각했기 때문에 그렇게 생각했던 것 같다.&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;물론 Aws에 배포하면 좋겠지만, 프리티어에 쿠버네티스를 적용한다는건 거의 불가능에 가깝기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 환경으로 이번에 배운 쿠버네티스와 젠킨스 등으로 CI/CD를 구현하는것에 집중하기로 하였다.&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;진짜 사소한 문제 하나때문에 몇시간을 삽질하는 등, 쉬울줄 알았는데 내 마음대로 잘 안되어서 스트레스도 많이 받았다.&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;문제를 해결하는데는 오래걸렸지만 따로 정리해 놓음으로써 나중에 같은 문제가 발생해도 쉽게 해결가능할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팀 프로젝트의 의미&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전까지 나는 혼자 해결하려고 하는 성향이 조금 강했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그도 그럴게 개인프로젝트만 하던 기간도 길었고 사실 협업을 하는것도 서툴렀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;이번에는 그렇게 하지않고 팀원들과 좀더 적극적으로 소통하며 업무를 분배하려고 노력하였다.&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;나 혼자서 다 해결하려고 하면 그건 더이상 팀 프로젝트가 아니라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 프로젝트는 나만 잘해서 되는것도 아니고 모두가 같이 잘해야하는 게임이기에 팀원을 믿고 기대는것도 좋은것 같다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회고를 마치며&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 수업은 끝났고 남은 것은 최종프로젝트만이 남았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부트캠프가 끝나도 회고록을 쓰는것은 아마 멈추지 않을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;마지막까지 회고록을 써내려가려고 한다.&lt;/p&gt;</description>
      <category>회고록</category>
      <category>한화시스템 beyond sw camp</category>
      <category>회고록</category>
      <author>jhss9747</author>
      <guid isPermaLink="true">https://jhss9747.tistory.com/51</guid>
      <comments>https://jhss9747.tistory.com/51#entry51comment</comments>
      <pubDate>Sun, 13 Apr 2025 22:12:51 +0900</pubDate>
    </item>
  </channel>
</rss>