<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>This, Too, Shall Pass Away</title>
    <link>https://greenring.tistory.com/</link>
    <description>이것저것 기록, 혼자 공부하는 개발자</description>
    <language>ko</language>
    <pubDate>Wed, 22 Jul 2026 07:21:18 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>greenring</managingEditor>
    <image>
      <title>This, Too, Shall Pass Away</title>
      <url>https://tistory1.daumcdn.net/tistory/5095898/attach/ec9d0ca2d63346148515aa04d7e345be</url>
      <link>https://greenring.tistory.com</link>
    </image>
    <item>
      <title>[Java] PrintWriter alert 한글 깨짐</title>
      <link>https://greenring.tistory.com/89</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  alert 창 한글이 깨져서 나오는 경우?&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #ee2323; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;응답의 문자 인코딩을 UTF-8로 설정 (한글 깨짐 방지)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1744960717932&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;response.setCharacterEncoding(&quot;UTF-8&quot;);
response.setContentType(&quot;text/html; charset=UTF-8&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 예시 코드&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1744960683061&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PrintWriter out = response.getWriter();
response.setCharacterEncoding(&quot;UTF-8&quot;);
response.setContentType(&quot;text/html; charset=UTF-8&quot;);
					
out.println(&quot;&amp;lt;script language='javascript'&amp;gt;&quot;);
out.println(&quot;alert('텍스트 작성');&quot;);
out.println(&quot;&amp;lt;/script&amp;gt;&quot;);
out.close();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/89</guid>
      <comments>https://greenring.tistory.com/89#entry89comment</comments>
      <pubDate>Fri, 18 Apr 2025 16:27:10 +0900</pubDate>
    </item>
    <item>
      <title>[VSCode] Prettier 자동 정렬  / 설정이 안되는 경우? (적용 안됨)</title>
      <link>https://greenring.tistory.com/88</link>
      <description>&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  저장할 때 코드 자동 정렬해주는 Prettier.&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;코드 스타일을 자동으로 맞추고 정리해준다.&lt;/span&gt;&lt;/h3&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. 설치&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;확장 버튼 (Ctrl + Shift + X ) 누르고 Prettier 검색.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;1914&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0uhom/btsMs8YAAhX/AZnr8ul82aGttbHEIdtSiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0uhom/btsMs8YAAhX/AZnr8ul82aGttbHEIdtSiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0uhom/btsMs8YAAhX/AZnr8ul82aGttbHEIdtSiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0uhom%2FbtsMs8YAAhX%2FAZnr8ul82aGttbHEIdtSiK%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;1914&quot; height=&quot;1014&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Ctrl + , 누르고 설정 들어가서 &lt;span style=&quot;background-color: #000000; color: #ffffff;&quot;&gt;format on save&lt;/span&gt; 검색&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #000000; color: #ffffff; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; Editor: 'format on save 부분 &lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;체크표시&lt;/span&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; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이렇게 설정까지 해줘야 Prettier 적용 가능하다.&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;1916&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ucE41/btsMuvyyec2/TdcmsEuNClhK1TY794Wb41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ucE41/btsMuvyyec2/TdcmsEuNClhK1TY794Wb41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ucE41/btsMuvyyec2/TdcmsEuNClhK1TY794Wb41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FucE41%2FbtsMuvyyec2%2FTdcmsEuNClhK1TY794Wb41%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;1916&quot; height=&quot;980&quot; data-origin-width=&quot;1916&quot; data-origin-height=&quot;980&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;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&amp;nbsp; 적용이 안되는 경우?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;설정하고 코드 저장했는데 자동정렬이 적용 안되는 경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;설정에서 &lt;span style=&quot;color: #ffffff; background-color: #000000;&quot;&gt;default formatter &lt;/span&gt;검색 후&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;background-color: #000000; text-align: start;&quot;&gt;Editor:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #000000; text-align: start;&quot;&gt;Default Formatter 부분을 &lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;Prettier - Code formatter&lt;/span&gt;&lt;/b&gt;로 설정해준다.&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;1920&quot; data-origin-height=&quot;1012&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evOcJO/btsMuttWOAE/Xnneuw08W6od8i8qJPiteK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evOcJO/btsMuttWOAE/Xnneuw08W6od8i8qJPiteK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evOcJO/btsMuttWOAE/Xnneuw08W6od8i8qJPiteK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FevOcJO%2FbtsMuttWOAE%2FXnneuw08W6od8i8qJPiteK%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;1920&quot; height=&quot;1012&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1012&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>etc</category>
      <category>vscode#extends#자동정렬#포맷터</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/88</guid>
      <comments>https://greenring.tistory.com/88#entry88comment</comments>
      <pubDate>Sun, 23 Feb 2025 23:45:06 +0900</pubDate>
    </item>
    <item>
      <title>[AWS S3] 업로드 API - URL이 다운로드 되는 문제? (Content-Type 설정)</title>
      <link>https://greenring.tistory.com/87</link>
      <description>&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;수정 전 코드&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1729334606194&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 요청 구성
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(filePath)
    .build();&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AWS S3에 파일 업로드 하기 전 요청을 구성하는 코드이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구성 후 S3에 업로드 된 파일의 경로, 즉 URL을 응답하는식으로 업로드 API를 작성하고 URL에 접근했는데&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내가 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;원하는 건 URL에 접속했을 때 브라우저에 바로 이미지가 보여지는 것&lt;/span&gt;이었지만&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;해당 URL은 이미지 다운로드&lt;/span&gt;만 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;수정 후 코드 (&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Content-Type 설정 추가&lt;/span&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1729334835681&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 요청 구성
    PutObjectRequest putObjectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(filePath)
        .contentType(file.getContentType()) // 업로드 시 파일의 Content-Type 설정 *  파일을 이미지로 인식 -&amp;gt; 다운로드 대신 웹 페이지에 표시
        .build();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이전에 코드가 다운로드 됐던 이유 :&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;파일이 어떤 종류인지 인식하지 못하기때문에&lt;/span&gt; 다운로드할 파일로 처리됐던 것이다.&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;따라서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Content-Type 설정을 통해 파일의 형식이 명확히 설정&lt;/span&gt;되어 브라우저가 해당 URL에 접근할 때 다운로드 하지않고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>etc</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/87</guid>
      <comments>https://greenring.tistory.com/87#entry87comment</comments>
      <pubDate>Sat, 19 Oct 2024 19:58:55 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스][python][해시] 의상</title>
      <link>https://greenring.tistory.com/86</link>
      <description>&lt;figure id=&quot;og_1727773025801&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;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&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/xC9mI/hyXaxe6eWM/EKrsKKcUexbBtdLlU5h510/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/2f0Lu/hyXaGXoXfc/aD4TB8uv1C0IMKieNMJU01/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&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/xC9mI/hyXaxe6eWM/EKrsKKcUexbBtdLlU5h510/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/2f0Lu/hyXaGXoXfc/aD4TB8uv1C0IMKieNMJU01/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 내가 작성한 코드&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1727773058697&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(clothes):
    dic = {}
    sum = 1
    
    # 의상 종류별로 의상이름 리스트 만들어서 넣어주기
    for cloth in clothes:
        if cloth[1] not in dic:
            dic[cloth[1]] = []
        dic[cloth[1]].append(cloth[0])
    
    # 의상 이름 개수 세기 위해 리스트로 만들기
    dicValList = list(dic.values())
    
    for i in range (len(dicValList)):
        # 의상 종류에서 아무것도 안입는 경우의 수 1을 추가
        # 예) 안경, 선글라스, 아무것도 안 입기
        sum *= len(dicValList[i]) + 1
        
    return sum - 1 # 전부 입지 않은 경우의 수 빼야함&lt;/code&gt;&lt;/pre&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;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 참고&lt;/span&gt;&lt;/b&gt;&amp;nbsp; &lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;sum에서 곱할 때 +1 하면서 곱하는 이유?)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;선택지를&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;dicValList[0] : 동그란 안경, 검정 선글라스, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;아무것도 안입기&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; dicValList[1] : 파란색 티셔츠, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;아무것도 안입기 &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;dicValList[2] : &lt;/span&gt;청바지, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;아무것도 안입기 &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;dicValList[3] : &lt;/span&gt;긴 코트, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;아무것도 안입기&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이런식으로 구성한다고 생각하며 +1를 하였다. &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;font-family: 'Noto Sans Light';&quot;&gt;그 이유는 예를 들어 의상을 구성할 때&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;동그란 안경 +&amp;nbsp; 파란색 티셔츠&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;동그란 안경 + 아무것도 안입기&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;이런식으로 구성이 가능하기때문에 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;1개(동그란 안경)만 의상을 착용한 경우도 나타낼 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;단, &lt;u&gt;아무것도 안입기 + &lt;/u&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;아무것도 안입기 + &lt;/u&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;아무것도 안입기 + &lt;/u&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;아무것도 안입기&lt;/u&gt; 도 sum에 포함되기 때문에&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;이건 빼줘야하므로 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;-1을 하면서 return한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>알고리즘 문제풀이/프로그래머스</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/86</guid>
      <comments>https://greenring.tistory.com/86#entry86comment</comments>
      <pubDate>Tue, 1 Oct 2024 18:08:01 +0900</pubDate>
    </item>
    <item>
      <title>[Spring AOP] @Cacheable 캐싱 적용 안 될 때 해결법 (Redis 캐시 확인)</title>
      <link>https://greenring.tistory.com/85</link>
      <description>&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  @Cacheable &lt;/b&gt;&lt;b&gt;캐싱 안 먹는 이유? (&lt;/b&gt;&lt;b&gt;Spring AOP)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Spring에서 @Cacheable 써서 캐싱할 때,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;같은 클래스 안에서 메서드 부르면 AOP가 안 먹힌다. 그 이유는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Spring AOP는 &lt;b&gt;프록시 객체&lt;/b&gt;로 동작&lt;/span&gt;하는데, 클래스 내부에서 자기 자신을 호출하면 프록시가 아니라 해당 메서드를 불러버리기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #f6e199;&quot;&gt; 프록시는 외부에서 해당 메서드가 호출될 때만 동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725786087388&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  @Service
  public class userService {
  
      public testResponse test(Long id) {
      ...
      	  // user 정보 얻기
          User user = getUser(id);
      ...
      }

	  // 캐싱 적용
      @Cacheable(value = &quot;userCache&quot;, key = &quot;#root.args[0]&quot;)
      public User getUser(id){
        return userRepository.findById(id)
      }
 
 }&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 해결방법 첫번째, 서비스 분리&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;캐싱할 메서드를 다른 서비스(UserCacheService)로 빼버린다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725786577350&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class UserCacheService {
    @Autowired
    private UserRepository userRepository;
    
    @Cacheable(value = &quot;userCache&quot;, key = &quot;#root.args[0]&quot;)
    public User getUser(Long id){
        return userRepository.findById(id);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 해결방법 두번째, &lt;/span&gt;자기 자신을 빈으로 주입&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 서비스 나누기 싫다면? &lt;b&gt;자기 자신을 @Autowired을 통해 Bean으로 주입한다&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러면 자기 자신 호출할 때도 프록시를 거치니까 AOP 적용되고 캐싱도 잘 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1725786743535&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class UserService {

    @Autowired
    private UserService self;  // 자기 자신을 주입

    public TestResponse test(Long id) {
        User user = self.getUser(id);  // 프록시를 거쳐서 호출
    }

    @Cacheable(value = &quot;userCache&quot;, key = &quot;#root.args[0]&quot;)
    public User getUser(Long id){
        return userRepository.findById(id);
    }
}&lt;/code&gt;&lt;/pre&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt; Redis로 캐시 확인하는 방법&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;해당 프로젝트는&amp;nbsp;Redis를 캐시 저장소로 설정했다. (&lt;b&gt;Redis는 Docker로 실행&lt;/b&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;따라서 캐싱이 잘 적용됐는지 확인하기 위해&amp;nbsp;Redis CLI 사용.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #dddddd;&quot;&gt; Redis Docker 컨테이너 실행하고 Spring에서 Redis와 연동됐다는 가정하에,&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1) &lt;b&gt;Redis CLI 접속&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Docker로 실행 중인 Redis에 접속하려면, 터미널에서 Redis CLI에 들어가서 명령어를 입력할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725787608240&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec -it [redis 컨테이너 이름] redis-cli&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;2) 캐시된 키 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 Redis에 저장된 모든 캐시 키를 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725787642835&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;keys *&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/85</guid>
      <comments>https://greenring.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 8 Sep 2024 18:34:23 +0900</pubDate>
    </item>
    <item>
      <title>[도커(Docker)] 에러 발생 (포트 충돌)</title>
      <link>https://greenring.tistory.com/84</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  도커 컨테이너 실행 시 에러 발생할 때? (포트 충돌인 경우)&lt;/b&gt;&lt;/h4&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;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✅ 1. 재시작&lt;/span&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;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;간혹 Docker 자체의 문제로 인해 포트가 해제되지 않는 경우가 있다.&lt;/span&gt;&lt;/p&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1724413462991&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker restart [docker_서비스_이름]&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;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✅&lt;/span&gt;&lt;/b&gt;&amp;nbsp; 2. 현재 포트 점유 확인&lt;/span&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;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;특정 포트번호를 사용하는 프로그램이나 다른 컨테이너가 있는지 확인해야 한다.&lt;/span&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;pre id=&quot;code_1724413520422&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;netstat -ano | findstr : 포트번호&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;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;출력된 결과에서 PID (프로세스 ID)를 확인한 후,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;해당 PID를 사용하고 있는 프로그램을 종료하거나, 다른 포트를 사용할 수 있도록 설정을 시도해본다.&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>etc</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/84</guid>
      <comments>https://greenring.tistory.com/84#entry84comment</comments>
      <pubDate>Fri, 23 Aug 2024 20:46:37 +0900</pubDate>
    </item>
    <item>
      <title>[도커(Docker)] MySQL 컨테이너 비밀번호 잊어버린 경우</title>
      <link>https://greenring.tistory.com/83</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&amp;nbsp; Enter Password: &lt;span style=&quot;background-color: #f6e199;&quot;&gt;비밀번호를 잊어버렸을 때?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1723457541387&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec -it [컨테이너 이름] bash
mysql -u root -p
Enter Password:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️ 아래 명령어를 실행해보자. PASSWORD를 바로 확인할 수 있다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1723457786817&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec [컨테이너 이름] printenv | findstr MYSQL_ROOT_PASSWORD&lt;/code&gt;&lt;/pre&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;  참고 - 도커 설치부터 MySQL 실행까지&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;figure id=&quot;og_1723457954693&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 Docker 컨테이너 접속 (Docker을 활용한 개발 환경 구성)&quot; data-og-description=&quot;✏️ Docker란? (참고:https://greenring.tistory.com/46) ✏️ Docker을 활용하여 MySQL에 접속하는 이유 : 새로운 환경마다 MySQL을 설치 안해줘도됨. MySQL 이미지를 내려받아 컨테이너를 구성하면 효율적. ✏️ &quot; data-og-host=&quot;greenring.tistory.com&quot; data-og-source-url=&quot;https://greenring.tistory.com/47&quot; data-og-url=&quot;https://greenring.tistory.com/47&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xJr2q/hyWOk7DJN7/asHDrhCOdTmd02rxMav2s0/img.png?width=568&amp;amp;height=119&amp;amp;face=0_0_568_119,https://scrap.kakaocdn.net/dn/XqCLu/hyWOmqQjwe/MhaYVCa7b3OARKo7Su9KKK/img.png?width=568&amp;amp;height=119&amp;amp;face=0_0_568_119&quot;&gt;&lt;a href=&quot;https://greenring.tistory.com/47&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://greenring.tistory.com/47&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xJr2q/hyWOk7DJN7/asHDrhCOdTmd02rxMav2s0/img.png?width=568&amp;amp;height=119&amp;amp;face=0_0_568_119,https://scrap.kakaocdn.net/dn/XqCLu/hyWOmqQjwe/MhaYVCa7b3OARKo7Su9KKK/img.png?width=568&amp;amp;height=119&amp;amp;face=0_0_568_119');&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 Docker 컨테이너 접속 (Docker을 활용한 개발 환경 구성)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;✏️ Docker란? (참고:https://greenring.tistory.com/46) ✏️ Docker을 활용하여 MySQL에 접속하는 이유 : 새로운 환경마다 MySQL을 설치 안해줘도됨. MySQL 이미지를 내려받아 컨테이너를 구성하면 효율적. ✏️&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;greenring.tistory.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>etc</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/83</guid>
      <comments>https://greenring.tistory.com/83#entry83comment</comments>
      <pubDate>Mon, 12 Aug 2024 19:21:09 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Reflection API</title>
      <link>https://greenring.tistory.com/82</link>
      <description>&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;  &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;Reflection API란?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;구체적인 클래스 타입을 알지 못해도&lt;/span&gt; 메서드, 타입, 변수 등 해당 클래스의 정보에 접근할 수 있게 해주는 Java API이다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708251059371&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Member {
	private String name;
	private int age;

	public Member(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void memberTest() {
		System.out.println(&quot;test입니다.&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1708251059377&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static void main(String[] args) {
    Object obj = new Member(&quot;kim&quot;, 10);
    obj.memberTest();    // 에러 발생
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;obj는 Object로 타입이 결정(&lt;span style=&quot;background-color: #ffffff; color: #ee2323;&quot;&gt;java는 컴파일 시점에 타입이 결정&lt;/span&gt;되므로 여기서 obj는 Object로 타입이 결정된다.)됐으므로&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Object 클래스 메서드, 변수들만 사용이 가능해서 Member클래스의 memberTest 사용 시 에러가 발생한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;(Member 클래스의 구체적 타입을 모르기 때문이다.)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때&amp;nbsp;Member클래스의 정보에 접근 가능하게 해주는 것이&amp;nbsp;&lt;span style=&quot;text-align: start;&quot;&gt;Reflection API이다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;(* 사용법 참고 &lt;/span&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.baeldung.com/java-reflection&quot;&gt;https://www.baeldung.com/java-reflection)&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이런 동작이 가능한 이유는 JVM가 실행되면서 코드가 컴파일러에 의해 바이트 코드로 변환되고, static영역에 저장된다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;Reflection API는 이 static 영역에 저장된 정보를 활용하는 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;그러나, 우리가 실제로 코드를 작성할 때는 구체적인 클래스를 모르는 일은 거의 없다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;따라서 애플리케이션 개발보다 프레임워크나 라이브러리에서 많이 사용된다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/82</guid>
      <comments>https://greenring.tistory.com/82#entry82comment</comments>
      <pubDate>Sun, 18 Feb 2024 19:41:07 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] Spring Data JPA - Entity에 기본 생성자가 필요한 이유?</title>
      <link>https://greenring.tistory.com/81</link>
      <description>&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  Spring Data JPA에서 Entity에 기본 생성자가 필요한 이유?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 필요한 이유는 동적으로 객체 생성 시&amp;nbsp;&lt;span style=&quot;color: #d44c47;&quot; data-token-index=&quot;1&quot;&gt;Reflection API&lt;/span&gt; 를 활용하기 때문이다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #d44c47;&quot; data-token-index=&quot;3&quot;&gt;JPA는 DB 값을 객체 필드에 주입할 때 기본 생성자로 객체를 생성한 후&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199; color: #d44c47;&quot; data-token-index=&quot;4&quot;&gt;Reflection API&lt;/span&gt;&lt;span style=&quot;color: #d44c47;&quot; data-token-index=&quot;5&quot;&gt;를 사용하여 값을 매핑한다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;때문에 기본 생성자가 없다면&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #eb5757;&quot; data-token-index=&quot;7&quot;&gt;Reflection&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;은 해&lt;/span&gt;당 객체를 생성 할 수 없기 때문에&amp;nbsp;JPA의 Entity에는 기본 생성자가 필요하다.&lt;/span&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;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;text-align: start;&quot;&gt; &amp;nbsp;&lt;/span&gt;Reflection API :&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://greenring.tistory.com/82&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://greenring.tistory.com/82&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;기본 생성자를 'public', 'protected'로 선언해야하는 이유?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;Entity 기본 생성자의 접근 제어자는 private로 선언할 수 없다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그 이유는, JPA의 Entity 조회 방식 중 하나인 &lt;span style=&quot;color: #ee2323;&quot;&gt;'&lt;span style=&quot;background-color: #f6e199;&quot;&gt;지연로딩&lt;/span&gt;'&lt;span style=&quot;color: #000000;&quot;&gt;의&lt;/span&gt; '&lt;span style=&quot;background-color: #f6e199;&quot;&gt;프록시 객체&lt;/span&gt;'&lt;/span&gt;와 관련이 있다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;지연로딩 시 사용되는 프록시 객체는 원본 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Entity를 &lt;/span&gt;상속해서 만들기때문에 원본 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Entity의 기본생성자가 private일 수 없는것이다.&amp;nbsp;&lt;/span&gt;&lt;/span&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;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;   지연로딩, 즉시로딩 :&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;지연로딩&lt;/b&gt; (&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;0&quot;&gt;Lazy Loading&lt;/span&gt;) : &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 지연 로딩은 연관된 엔티티를 &lt;u&gt;실제로 사용할 때 쿼리를 실행&lt;/u&gt;하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;부모 엔티티를 조회할 때 &lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;1&quot;&gt;연관된 자식 엔티티는 &lt;u&gt;초기에는 로딩되지 않고&lt;/u&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;3&quot;&gt;&lt;u&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;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이를 통해 불필요한 데이터 로딩을 최소화할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;(*프록시 객체 : 실제 사용될 때까지 조회를 지연하기위해 &lt;u&gt;가짜 객체&lt;/u&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;0&quot;&gt;&lt;b&gt;즉시로딩&lt;/b&gt; (Eager Loading)&lt;/span&gt;: &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;부모 엔티티를 조회할 때 &lt;u&gt;연관된 자식 엔티티도 함께 조회&lt;/u&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 경우, 쿼리는 부모 엔티티를 조회할 때 실행된다. &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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;</description>
      <category>Spring</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/81</guid>
      <comments>https://greenring.tistory.com/81#entry81comment</comments>
      <pubDate>Sun, 18 Feb 2024 19:34:49 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] JPA 쿼리 생성 (쿼리 메소드, JPQL, QueryDSL)</title>
      <link>https://greenring.tistory.com/80</link>
      <description>&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;  &lt;/span&gt;JPA에서 제공하는 여러가지 쿼리 생성 방법을 알아보자.&lt;/span&gt;&lt;/b&gt;&lt;/h4&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;1. 쿼리 메소드(Query Methods) &lt;/b&gt;&lt;b&gt;:&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #374151; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;메소드 이름을 통해 JPQL 쿼리를 생성하는 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Spring Data JPA에서 자동으로 메소드 이름을 분석하여 JPQL을 생성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;메서드 이름을 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;특정한 규칙&lt;/span&gt;에 맞게 작성하면, &lt;u&gt;Spring Data JPA&lt;/u&gt;는 해당 메서드를 실행할 때 &lt;u&gt;자동으로 쿼리를 생성&lt;/u&gt;하여 데이터베이스에 전달한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703331050147&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface PostRepository extends JpaRepository&amp;lt;Post, Long&amp;gt; {
    
    // 제목에 특정 키워드가 포함된 게시글 검색
    List&amp;lt;Post&amp;gt; findByTitleContaining(String keyword);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예를 들어, findByTitleContaining 메서드는 다음과 같은 역할을 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;findBy &lt;/b&gt;: 메서드 이름의 시작 부분으로, &quot;findBy&quot; 다음에 오는 속성명으로 &lt;u&gt;쿼리를 생성&lt;/u&gt;한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Title &lt;/b&gt;: 엔터티 클래스의 속성 중 하나이다. 여기서는 title이라는 &lt;u&gt;속성을 의미&lt;/u&gt;한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Containing &lt;/b&gt;: 속성에 대한 &lt;u&gt;조건&lt;/u&gt;을 나타내며, 해당 속성이 특정 키워드를 포함하는지를 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;따라서, findByTitleContaining은 &quot;title&quot; 속성에서 특정 키워드를 포함하는 게시글을 찾는 쿼리를 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Spring Data JPA는 이 메서드를 실행할 때, 자동으로 쿼리를 생성하고 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예를 들어, 메서드를 호출할 때 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;findByTitleContaining(&quot;Java&quot;)&lt;/span&gt;와 같이 호출하면, Spring Data JPA는 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&quot;title에 'Java'를 포함하는 게시글을 찾아라&quot;는 쿼리를 생성하고 실행&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. JPQL (Java Persistence Query Language) :&amp;nbsp;&lt;/b&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: #374151; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 쿼리 메소드는 특정한 규칙을 따르며, 이를 통해 자주 사용되는 CRUD 기능을 편리하게 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt; 하지만 복잡한 쿼리를 표현하기에는 한계가 있을 수 있다. 이런 경우에는 &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;@Query&lt;/span&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt; 어노테이션을 사용하여 직접 JPQL을 작성&lt;/span&gt;한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;객체지향 쿼리 언어&lt;/span&gt;로, 엔티티 객체를 대상으로 쿼리를 작성할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;SQL과 유사하지만 테이블이 아닌 엔티티에 대해 쿼리를 작성한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1703331298763&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface PostRepository extends JpaRepository&amp;lt;Post, Long&amp;gt; {

    @Query(&quot;SELECT p FROM Post p WHERE p.title LIKE %:keyword%&quot;)
    List&amp;lt;Post&amp;gt; findByTitleContainingCustom(@Param(&quot;keyword&quot;) String keyword);

    // 다른 사용자 정의 쿼리 메서드들...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;SELECT p &lt;/b&gt;: 엔티티 객체인 Post를 선택합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;FROM Post p &lt;/b&gt;: &lt;u&gt;Post &lt;/u&gt;엔터티를 대상으로 쿼리를 실행합니다. (p : Post의 별칭)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;WHERE p.title LIKE %:keyword%&lt;/b&gt;: &lt;u&gt;title&lt;/u&gt; 속성이 특정 키워드를 포함하는 경우를 선택합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;JPQL은 엔티티 객체를 기반으로 작성되기 때문에 테이블과 컬럼의 이름이 아닌 &lt;u&gt;&lt;span style=&quot;letter-spacing: 0px;&quot; data-token-index=&quot;1&quot;&gt;엔터티 클래스와 그 속성명을 사용&lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;합니다. 이를 통해 &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; background-color: #dddddd;&quot; data-token-index=&quot;3&quot;&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: #ee2323; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;만약 &lt;span style=&quot;background-color: #f3c000; color: #ffffff;&quot;&gt;네이티브 SQL&lt;/span&gt;을 사용하고 싶다면.. &lt;u&gt;nativeQuery 속성을 true&lt;/u&gt;로 설정 &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703331738534&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Query(value = &quot;SELECT * FROM post WHERE title LIKE %:keyword%&quot;, nativeQuery = true)
List&amp;lt;Post&amp;gt; findByTitleContainingNative(@Param(&quot;keyword&quot;) String keyword);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이렇게 하면 직접 SQL을 작성하여 원하는 쿼리를 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;다만 주의할 점은 &lt;u&gt;네이티브 SQL을 사용할 때는 데이터베이스 종속성이 생길 수 있으므로(보안 문제 발생 가능성도 있음)&lt;/u&gt;, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가능한 JPQL을 사용하여 데이터베이스에 독립적인 쿼리를 작성하는 것이 좋다.&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. QueryDSL(Domain Specific Language) :&amp;nbsp;&lt;/b&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;@Query 어노테이션은 명시적인 JPQL을 작성할 수 있게 해주지만, 쿼리가 복잡해지면 가독성이나 유지보수 측면에서 한계가 있을 수 있다. 이런 경우에&lt;u&gt; QueryDSL을 사용하면 좀 더 강력하고 유연한 쿼리를 작성할 수 있다.&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;QueryDSL은&amp;nbsp;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;JPQL을&amp;nbsp;자바&amp;nbsp;코드로&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;도와주는&amp;nbsp;라이브러리&lt;/span&gt;로, 코드 자체에서 쿼리를 구성할 수 있게 해준다. 이를 통해 컴파일 시점에서 &lt;u&gt;타입&amp;nbsp;안정성을&amp;nbsp;확보&lt;/u&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: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp; QueryDSL 예시 코드를 보며 전체적인 흐름을 확인해보자.&lt;/span&gt;&lt;/b&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 1) 엔티티 클래스 (&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot; data-token-index=&quot;1&quot;&gt;Post&lt;/span&gt;&lt;/b&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;엔티티 클래스는 데이터베이스의 테이블을 나타내는데 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;QueryDSL은 이 엔티티 클래스를 기반으로 Query 타입을 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703332978260&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

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

    private String title;

    // Getter, Setter, 기타 메서드...
}&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2) QueryDSL Query 타입 (&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot; data-token-index=&quot;1&quot;&gt;QPost&lt;/span&gt;):&lt;/b&gt; &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt; QPost&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt; 클래스는 QueryDSL을 사용하여 JPA 엔티티인 &lt;/span&gt;Post&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;&lt;u&gt;에 대한 타입 안전한(Query 타입) 표현을 정의한 클래스이다.&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: #374151; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 클래스를 사용하면 코드에서 엔티티의 속성에 대한 오타나 오류를 컴파일 시간에 확인할 수 있다.&lt;/span&gt;&lt;span style=&quot;color: #374151; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703334468477&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.StringPath;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.Expressions;

public class QPost extends EntityPathBase&amp;lt;Post&amp;gt; {
    public final StringPath title = createString(&quot;title&quot;);
    public final NumberPath&amp;lt;Long&amp;gt; id = createNumber(&quot;id&quot;, Long.class);

    public QPost(String variable) {
        super(Post.class, variable);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; QPost extends EntityPathBase&amp;lt;Post&amp;gt; :&lt;/b&gt; &lt;u&gt;EntityPathBase&lt;/u&gt;는 QueryDSL에서 사용하는 기본 클래스로, &lt;u&gt;엔티티에 대한 QueryDSL Query 타입을 생성하기 위한 메타 모델 클래스를 정의하는 데 사용된다.&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;public final StringPath title = createString(&quot;title&quot;); :&lt;/b&gt; 이 부분은 title 필드에 대한 QueryDSL &lt;u&gt;Query 타입을 정의한다.&lt;/u&gt;&amp;nbsp;&lt;u&gt;StringPath는 문자열&lt;/u&gt;에 대한 QueryDSL 타입을 나타내며, createString(&quot;title&quot;)은 title이라는 필드에 대한 QueryDSL 표현식을 생성한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;public final NumberPath&amp;lt;Long&amp;gt; id = createNumber(&quot;id&quot;, Long.class); :&lt;/b&gt; 이 부분은 id 필드에 대한 QueryDSL Query 타입을 정의한다. &lt;u&gt;NumberPath&amp;lt;Long&amp;gt;는 숫자(Long)&lt;/u&gt;에 대한 QueryDSL 타입을 나타내며, createNumber(&quot;id&quot;, Long.class)은 id라는 필드에 대한 QueryDSL 표현식을 생성한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; public QPost(String variable) { super(Post.class, variable); } &lt;/b&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;&lt;b&gt;:&lt;/b&gt;&amp;nbsp;&lt;u&gt;생성자는 &lt;/u&gt;&lt;/span&gt;&lt;u&gt;QPost&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;&lt;u&gt; 클래스의 인스턴스를 초기화한다.&lt;/u&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;Post.class&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;는 이 QueryDSL Query 타입이 &lt;u&gt;어떤 엔티티를 대상&lt;/u&gt;으로 하는지를 나타내며, &lt;/span&gt;&lt;u&gt;variable&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;은 QueryDSL에서 &lt;u&gt;사용될 변수명&lt;/u&gt;을 지정한다.&lt;/span&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #374151; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 이 클래스를 사용하면 QueryDSL을 활용하여 동적으로 쿼리를 작성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;예를 들어, &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;QPost.post.title.eq(&quot;제목&quot;)&lt;/span&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;와 같은 형태로 사용하여 &lt;/span&gt;&lt;u&gt;title&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;&lt;u&gt; 필드가 &quot;제목&quot;과 같은지&lt;/u&gt;를 나타내는 조건을 만들 수 있다. QueryDSL을 사용하면 &lt;u&gt;타입 안정성(type safety)을 확보&lt;/u&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 3) Repository 인터페이스 (&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot; data-token-index=&quot;1&quot;&gt;PostRepository&lt;/span&gt;):&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; PostRepository&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt; 인터페이스는 Spring Data JPA의 &lt;/span&gt;&lt;u&gt;CrudRepository&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;&lt;u&gt;를 확장&lt;/u&gt;하고, QueryDSL을 사용하여 &lt;u&gt;동적인 쿼리를 처리하기 위한 &lt;/u&gt;&lt;/span&gt;&lt;u&gt;QuerydslPredicateExecutor&lt;/u&gt;&lt;span style=&quot;color: #374151; text-align: left;&quot;&gt;&lt;u&gt;를 구현한다&lt;/u&gt;. (&lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;Spring Data JPA의 기본 기능 정의)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703335647279&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.CrudRepository;

public interface PostRepository extends CrudRepository&amp;lt;Post, Long&amp;gt;, QuerydslPredicateExecutor&amp;lt;Post&amp;gt; {
    // 다른 메서드들...

    // QueryDSL을 사용한 동적인 쿼리
    List&amp;lt;Post&amp;gt; findAll(Predicate predicate);
    
    // Spring Data JPA가 제공하는 메서드 활용
    List&amp;lt;Post&amp;gt; findByTitle(String title);
}&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4) Custom Repository 인터페이스 (&lt;span style=&quot;background-color: #dddddd;&quot;&gt;CustomPostRepository&lt;/span&gt;) : &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;QueryDSL을 사용한 동적 쿼리를 직접 구현하는 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #374151; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 사용자가 정의한 쿼리 메서드를 추가한 인터페이스.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703335974225&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.List;

public interface CustomPostRepository {
    // QueryDSL을 사용한 동적인 쿼리
    List&amp;lt;Post&amp;gt; findPostsByTitle(String keyword);
}&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5) Custom Repository 구현 클래스 (&lt;span style=&quot;background-color: #dddddd; color: #000000;&quot; data-token-index=&quot;1&quot;&gt;PostRepositoryImpl&lt;/span&gt;): &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #111827; text-align: left;&quot;&gt;CustomPostRepository&lt;/span&gt; 인터페이스에서 정의된 메서드를 구현하는 클래스.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 여기에서 QueryDSL을 사용하여 동적인 쿼리를 작성하고 실행한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703336106264&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.querydsl.jpa.impl.JPAQueryFactory;

import javax.persistence.EntityManager;

public class PostRepositoryImpl implements CustomPostRepository {

    private final JPAQueryFactory queryFactory;
    private final QPost qPost = QPost.post;

    public PostRepositoryImpl(EntityManager entityManager) {
        this.queryFactory = new JPAQueryFactory(entityManager);
    }

    @Override
    public List&amp;lt;Post&amp;gt; findPostsByTitle(String keyword) {
        return queryFactory.selectFrom(qPost)
                .where(qPost.title.like(&quot;%&quot; + keyword + &quot;%&quot;))
                .fetch();
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;✏️&lt;/span&gt;&amp;nbsp;정리&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 외에&amp;nbsp; &lt;u&gt;Named Query, Criteria API&lt;/u&gt; 방법도 존재한다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 여러 가지 방법을 적절히 조합하여 사용하는 것이 중요하며, 간단한 쿼리에는 메서드 이름 규칙을, 복잡한 쿼리에는 @Query 어노테이션을 또는 QueryDSL을 활용하는 것이 좋다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>greenring</author>
      <guid isPermaLink="true">https://greenring.tistory.com/80</guid>
      <comments>https://greenring.tistory.com/80#entry80comment</comments>
      <pubDate>Sat, 23 Dec 2023 22:13:46 +0900</pubDate>
    </item>
  </channel>
</rss>