<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>seungmin576 님의 블로그</title>
    <link>https://seungmin576.tistory.com/</link>
    <description>seungmin576 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Sat, 1 Aug 2026 20:33:09 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>seungmin576</managingEditor>
    <item>
      <title>ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) MacOs 기준</title>
      <link>https://seungmin576.tistory.com/159</link>
      <description>&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;brew&amp;nbsp;services&amp;nbsp;stop&amp;nbsp;mysql&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;mysqld_safe&amp;nbsp;--skip-grant-tables&amp;nbsp;&amp;amp;&lt;br /&gt;2번 안될 경우&lt;br /&gt;ps&amp;nbsp;aux&amp;nbsp;|&amp;nbsp;grep&amp;nbsp;mysqld&lt;br /&gt;sudo&amp;nbsp;kill&amp;nbsp;-9&amp;nbsp;[프로세스ID]&lt;br /&gt;sudo mysqld_safe --skip-grant-tables &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&amp;nbsp;&lt;br /&gt;혹은 sudo&amp;nbsp;/opt/homebrew/opt/mysql/bin/mysqld_safe&amp;nbsp;--skip-grant-tables&lt;/li&gt;
&lt;li&gt;mysql -u root&lt;/li&gt;
&lt;li&gt;ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 원하는 비번&lt;br /&gt;플러그인 오류시 ALTER&amp;nbsp;USER&amp;nbsp;'root'@'localhost'&amp;nbsp;IDENTIFIED&amp;nbsp;BY&amp;nbsp;'원하는비번';&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;pkill&amp;nbsp;mysqld&lt;/li&gt;
&lt;li&gt;brew&amp;nbsp;services&amp;nbsp;start&amp;nbsp;mysql&lt;br /&gt;안되면 sudo&amp;nbsp;brew&amp;nbsp;services&amp;nbsp;start&amp;nbsp;mysql&lt;/li&gt;
&lt;li&gt;mysql&amp;nbsp;-u&amp;nbsp;root&amp;nbsp;-p&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>오류, 기능, 문제해결(SQL)</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/159</guid>
      <comments>https://seungmin576.tistory.com/159#entry159comment</comments>
      <pubDate>Thu, 24 Apr 2025 12:51:06 +0900</pubDate>
    </item>
    <item>
      <title>AWS EC2 ubuntu 일때 docker 설치방법</title>
      <link>https://seungmin576.tistory.com/158</link>
      <description>&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;sudo&amp;nbsp;apt-get&amp;nbsp;update&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;apt-get&amp;nbsp;install&amp;nbsp;apt-transport-https&amp;nbsp;ca-certificates&amp;nbsp;curl&amp;nbsp;software-properties-common&lt;/li&gt;
&lt;li&gt;curl&amp;nbsp;-fsSL&amp;nbsp;https://download.docker.com/linux/ubuntu/gpg&amp;nbsp;|&amp;nbsp;sudo&amp;nbsp;tee&amp;nbsp;/etc/apt/trusted.gpg.d/docker.asc&lt;/li&gt;
&lt;li&gt;curl&amp;nbsp;-fsSL&amp;nbsp;https://download.docker.com/linux/ubuntu/gpg&amp;nbsp;|&amp;nbsp;sudo&amp;nbsp;apt-key&amp;nbsp;add&amp;nbsp;-&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;add-apt-repository&amp;nbsp;&quot;deb&amp;nbsp;[arch=amd64]&amp;nbsp;https://download.docker.com/linux/ubuntu&amp;nbsp;$(lsb_release&amp;nbsp;-cs)&amp;nbsp;stable&quot;&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;apt-get&amp;nbsp;update&lt;br /&gt;sudo&amp;nbsp;apt-get&amp;nbsp;install&amp;nbsp;docker-ce&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;systemctl&amp;nbsp;start&amp;nbsp;docker&lt;/li&gt;
&lt;li&gt;sudo&amp;nbsp;systemctl&amp;nbsp;enable&amp;nbsp;docker&lt;/li&gt;
&lt;li&gt;sudo usermod -aG docker $USER&lt;/li&gt;
&lt;li&gt;docker&amp;nbsp;--version&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설명 추후 추가&lt;/p&gt;</description>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/158</guid>
      <comments>https://seungmin576.tistory.com/158#entry158comment</comments>
      <pubDate>Tue, 22 Apr 2025 15:04:01 +0900</pubDate>
    </item>
    <item>
      <title>ElasticSearch 사용시 nori 관련 오류</title>
      <link>https://seungmin576.tistory.com/157</link>
      <description>&lt;pre id=&quot;code_1743379837263&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Caused by: co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/indices.create] failed: [illegal_argument_exception] Unknown filter type [nori_part_of_speech] for [nori_part_of_speech]
	at co.elastic.clients.transport.ElasticsearchTransportBase.getApiResponse(ElasticsearchTransportBase.java:345) ~[elasticsearch-java-8.15.5.jar:na]
	at co.elastic.clients.transport.ElasticsearchTransportBase.performRequest(ElasticsearchTransportBase.java:147) ~[elasticsearch-java-8.15.5.jar:na]
	at co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient.create(ElasticsearchIndicesClient.java:277) ~[elasticsearch-java-8.15.5.jar:na]
	at org.springframework.data.elasticsearch.client.elc.IndicesTemplate.lambda$doCreate$0(IndicesTemplate.java:147) ~[spring-data-elasticsearch-5.4.4.jar:5.4.4]
	at org.springframework.data.elasticsearch.client.elc.ChildTemplate.execute(ChildTemplate.java:71) ~[spring-data-elasticsearch-5.4.4.jar:5.4.4]
	... 72 common frames omitted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1711&quot; data-origin-height=&quot;467&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pWbpS/btsM0qZpbTC/vCK24AT3cVisTrDsdHZ1h1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pWbpS/btsM0qZpbTC/vCK24AT3cVisTrDsdHZ1h1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pWbpS/btsM0qZpbTC/vCK24AT3cVisTrDsdHZ1h1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpWbpS%2FbtsM0qZpbTC%2FvCK24AT3cVisTrDsdHZ1h1%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;1711&quot; height=&quot;467&quot; data-origin-width=&quot;1711&quot; data-origin-height=&quot;467&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1743379888325&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;analysis&quot;: {
      &quot;filter&quot;: {
      &quot;nori_readingform&quot;: {
        &quot;type&quot;: &quot;nori_readingform&quot;
      },
      &quot;nori_part_of_speech&quot;: {
        &quot;type&quot;: &quot;nori_part_of_speech&quot;,
        &quot;stoptags&quot;: [&quot;E&quot;, &quot;IC&quot;, &quot;J&quot;, &quot;SP&quot;, &quot;SSC&quot;, &quot;SSO&quot;, &quot;SC&quot;]
      },
      &quot;word_delimiter&quot;: {
        &quot;type&quot;: &quot;word_delimiter&quot;,
        &quot;split_on_case_change&quot;: true,
        &quot;split_on_numerics&quot;: true,
        &quot;generate_word_parts&quot;: true,
        &quot;generate_number_parts&quot;: true,
        &quot;catenate_all&quot;: false,
        &quot;catenate_words&quot;: false,
        &quot;preserve_original&quot;: false
      },
        &quot;custom_snowball_filter&quot;: {
          &quot;type&quot;: &quot;snowball&quot;,
          &quot;language&quot;: &quot;English&quot;
        }
    },
    &quot;analyzer&quot;: {
      &quot;korean&quot;: {
        &quot;type&quot;: &quot;custom&quot;,
        &quot;tokenizer&quot;: &quot;nori_tokenizer&quot;,
        &quot;filter&quot;: [&quot;nori_part_of_speech&quot;, &quot;nori_readingform&quot;]
      },
      &quot;custom_snowball&quot;: {
        &quot;type&quot;: &quot;custom&quot;,
        &quot;tokenizer&quot;: &quot;standard&quot;,
        &quot;filter&quot;: [&quot;lowercase&quot;, &quot;word_delimiter&quot;, &quot;custom_snowball_filter&quot;]
      },
     &quot;mixed_analyzer&quot; : {
       &quot;type&quot; : &quot;custom&quot;,
       &quot;tokenizer&quot; : &quot;nori_tokenizer&quot;,
       &quot;filter&quot; : [&quot;nori_part_of_speech&quot;, &quot;nori_readingform&quot;, &quot;word_delimiter&quot;, &quot;lowercase&quot;]
     }
    },
    &quot;normalizer&quot;: {
      &quot;lowercase_normalizer&quot;: {
        &quot;type&quot;: &quot;custom&quot;,
        &quot;filter&quot;: [&quot;lowercase&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;제가 작성한 ElasticSearch를 사용하기 위한 setting.json 파일인데 여기서 nori라는 형태소분석기를 사용하여 한국어를 형태소 분리하려 하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허나 오류의 주요 코드를 보시면&lt;/p&gt;
&lt;pre id=&quot;code_1743380022766&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Caused by: co.elastic.clients.elasticsearch._types.ElasticsearchException: [es/indices.create] failed: [illegal_argument_exception] Unknown filter type [nori_part_of_speech] for [nori_part_of_speech]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;filter 중 nori_part_of_speech 가 unknown 필터라면서 스프링 프로젝트가 실행되고 있지 않는 모습입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nori 형태소 분석기는 기본적으로 제공되는 것이 아닌 사용자가 ElasticSearch에 설치해야하기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 ElasticSearch 내부에 nori 형태소 분석기를 설치해주면 해결될 오류로 보입니다.&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;&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;docker를 이용한 nori 형태소 분석기 설치하는 방법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 저희의 프로젝트는 docker를 이용하여 elaticsearch를 이용 중 이기 때문에 docker를 이용하여 nori를 설치해야합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;docker-composefile.yml 이 존재하는 프로젝트 폴더로 ubuntu를 이용하여 경로를 이동합니다.&lt;br /&gt;
&lt;pre id=&quot;code_1743380357776&quot; class=&quot;awk&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;cd /mnt/d/projects/count10shop&lt;/code&gt;&lt;/pre&gt;
제 컴퓨터가 윈도우라서 &lt;b&gt;/mnt&lt;/b&gt; 라는 명령어를 붙여 사용했지만 윈도우가 아니신 분들은 &lt;b&gt;/mnt&lt;/b&gt; 는 빼시면 됩니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;b&gt;docker compose up&lt;/b&gt; 명령어를 통해 elasticsearch를 실행시킵니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csFAkO/btsM1qq6zOt/crr3V1WIvW9XwsGFMYCNb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csFAkO/btsM1qq6zOt/crr3V1WIvW9XwsGFMYCNb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csFAkO/btsM1qq6zOt/crr3V1WIvW9XwsGFMYCNb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsFAkO%2FbtsM1qq6zOt%2Fcrr3V1WIvW9XwsGFMYCNb1%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;557&quot; height=&quot;36&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;36&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;docker ps&lt;/b&gt; 명령어를 통해 elasticsearch의 container id 혹은 name을 확인합니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oubnh/btsM1JDHTIH/60WIGNBHJxIaMX3gz5ag7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oubnh/btsM1JDHTIH/60WIGNBHJxIaMX3gz5ag7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oubnh/btsM1JDHTIH/60WIGNBHJxIaMX3gz5ag7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Foubnh%2FbtsM1JDHTIH%2F60WIGNBHJxIaMX3gz5ag7K%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;1297&quot; height=&quot;51&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;docker exec -it &lt;/b&gt;(container id 또는 name을 입력한다.) &lt;b&gt;/bin/bash&lt;/b&gt; 명령어로 해당 컨테이너 내부로 이동합니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cK5LBl/btsM2I5pAJH/2uKWHT2608FQ2uMNOIUVyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cK5LBl/btsM2I5pAJH/2uKWHT2608FQ2uMNOIUVyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cK5LBl/btsM2I5pAJH/2uKWHT2608FQ2uMNOIUVyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcK5LBl%2FbtsM2I5pAJH%2F2uKWHT2608FQ2uMNOIUVyK%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;644&quot; height=&quot;48&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;./bin/elasticsearch-plugin &lt;/span&gt;&lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;install analysis-nori&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #383a42; text-align: start;&quot;&gt;명령어로 해당 컨테이너 내부에 nori 형태소 분석기를 설치합니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cR6xdu/btsM1JRcofs/KM3jKvhYasaUXMul932Fh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cR6xdu/btsM1JRcofs/KM3jKvhYasaUXMul932Fh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cR6xdu/btsM1JRcofs/KM3jKvhYasaUXMul932Fh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcR6xdu%2FbtsM1JRcofs%2FKM3jKvhYasaUXMul932Fh0%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;660&quot; height=&quot;93&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;b&gt;exit&lt;/b&gt; 을 입력하여 컨테이너에서 나온 뒤&lt;b&gt; docker compose stop&lt;/b&gt; 으로 멈추고 다시 &lt;b&gt;docker compose start&lt;/b&gt;로 재실행합니다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP3SK8/btsM2dxMdR8/84U0uDGuFPLBrvDVnmXBzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP3SK8/btsM2dxMdR8/84U0uDGuFPLBrvDVnmXBzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP3SK8/btsM2dxMdR8/84U0uDGuFPLBrvDVnmXBzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP3SK8%2FbtsM2dxMdR8%2F84U0uDGuFPLBrvDVnmXBzk%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;614&quot; height=&quot;55&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x5nUM/btsM1OkZw5l/S0vz7rUkUKOdfKKLUovBg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x5nUM/btsM1OkZw5l/S0vz7rUkUKOdfKKLUovBg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x5nUM/btsM1OkZw5l/S0vz7rUkUKOdfKKLUovBg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx5nUM%2FbtsM1OkZw5l%2FS0vz7rUkUKOdfKKLUovBg0%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;1041&quot; height=&quot;1034&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/157</guid>
      <comments>https://seungmin576.tistory.com/157#entry157comment</comments>
      <pubDate>Mon, 31 Mar 2025 09:29:35 +0900</pubDate>
    </item>
    <item>
      <title>ubuntu로 window 경로 접근하기, 컨테이너 접속하기</title>
      <link>https://seungmin576.tistory.com/156</link>
      <description>&lt;h3 data-end=&quot;175&quot; data-start=&quot;137&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Ubuntu에서 Windows 경로 접근하는 방법&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-end=&quot;223&quot; data-start=&quot;176&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;WSL2(Ubuntu)에서 Windows 드라이브 마운트 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-end=&quot;319&quot; data-start=&quot;224&quot; data-ke-size=&quot;size16&quot;&gt;Ubuntu(WSL2)에서는 Windows 드라이브가 &lt;b&gt;자동으로 /mnt 아래에 마운트&lt;/b&gt;됩니다.&lt;br /&gt;즉, D: 드라이브는 /mnt/d로 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;319&quot; data-start=&quot;224&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;319&quot; data-start=&quot;224&quot; data-ke-size=&quot;size16&quot;&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1743339977268&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd /mnt/d/projects/count10shop&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;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;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker exec -it &lt;b&gt;(접속할 컨테이너이름)&lt;/b&gt; /bin/bash&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;노리 설치방법&lt;/p&gt;
&lt;pre id=&quot;code_1743347050528&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;./bin/elasticsearch-plugin install analysis-nori&lt;/code&gt;&lt;/pre&gt;</description>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/156</guid>
      <comments>https://seungmin576.tistory.com/156#entry156comment</comments>
      <pubDate>Sun, 30 Mar 2025 22:06:24 +0900</pubDate>
    </item>
    <item>
      <title>도커 설치 window 방식 (wsl)</title>
      <link>https://seungmin576.tistory.com/155</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;제어판 -&amp;gt; 프로그램 및 기능 -&amp;gt; window 기능 켜기/ 끄기 -&amp;gt; Linux 용 windows 하위 시스템 켜야함.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dabzwb/btsMUOSSpqA/noHh8LYw8tueN4mC4gbrQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dabzwb/btsMUOSSpqA/noHh8LYw8tueN4mC4gbrQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dabzwb/btsMUOSSpqA/noHh8LYw8tueN4mC4gbrQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdabzwb%2FbtsMUOSSpqA%2FnoHh8LYw8tueN4mC4gbrQK%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;1084&quot; height=&quot;542&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;WSL 설치&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/wsl/install&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://learn.microsoft.com/ko-kr/windows/wsl/install&lt;/a&gt; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명렴프롬포트 또는 power Shell 관리자 권한으로 실행&lt;/p&gt;
&lt;pre id=&quot;code_1742864002001&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wsl --install
wsl --update
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴터 다시시작하면 알아서 ubuntu 설치를 함.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eDG0Ib/btsMT5OeL48/32KWSFHClZnNhlCSHNWcpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eDG0Ib/btsMT5OeL48/32KWSFHClZnNhlCSHNWcpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eDG0Ib/btsMT5OeL48/32KWSFHClZnNhlCSHNWcpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeDG0Ib%2FbtsMT5OeL48%2F32KWSFHClZnNhlCSHNWcpK%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;540&quot; height=&quot;134&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1742868972074&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wsl.exe -d Ubuntu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 입력하여 실행하거나 시작 검색창에서&amp;nbsp;ubuntu 치면 깔려있는데 실행하면 됨&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkvQQR/btsMUi7KsGt/9Qi910IJWHhBr04UAnUktK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkvQQR/btsMUi7KsGt/9Qi910IJWHhBr04UAnUktK/img.png&quot; data-alt=&quot;이건 Microsft store에서 깔려있는거 확인한 이미지.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkvQQR/btsMUi7KsGt/9Qi910IJWHhBr04UAnUktK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkvQQR%2FbtsMUi7KsGt%2F9Qi910IJWHhBr04UAnUktK%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;460&quot; height=&quot;539&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이건 Microsft store에서 깔려있는거 확인한 이미지.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하면 유저 이름이랑 비번 설정하는거 나오는데 대충 원하는대로 하기.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;115&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rfFXo/btsMUPRN7HA/8zWsEHsZzBMU5sKkxSgse1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rfFXo/btsMUPRN7HA/8zWsEHsZzBMU5sKkxSgse1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rfFXo/btsMUPRN7HA/8zWsEHsZzBMU5sKkxSgse1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrfFXo%2FbtsMUPRN7HA%2F8zWsEHsZzBMU5sKkxSgse1%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;368&quot; height=&quot;115&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;115&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행되면서 알아서 무슨 버전 깔려있는지 나오지만 한번 더 깔려있는 버전이 뭔지 확인하는 코드&lt;/p&gt;
&lt;pre id=&quot;code_1742867033558&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;lsb_release -a&lt;/code&gt;&lt;/pre&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;346&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCa1Vc/btsMUqrbQkm/Wtx69kYyfY7zJotKL2zho0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCa1Vc/btsMUqrbQkm/Wtx69kYyfY7zJotKL2zho0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCa1Vc/btsMUqrbQkm/Wtx69kYyfY7zJotKL2zho0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCa1Vc%2FbtsMUqrbQkm%2FWtx69kYyfY7zJotKL2zho0%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;346&quot; height=&quot;96&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ubuntu에 docker 설치&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1742870452061&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# docker engine gpg 키 등록
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# apt source 에 docker 관련 추가
echo \
  &quot;deb [arch=&quot;$(dpkg --print-architecture)&quot; signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  &quot;$(. /etc/os-release &amp;amp;&amp;amp; echo &quot;$VERSION_CODENAME&quot;)&quot; stable&quot; | \
  sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
sudo apt-get update

# docker engine 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin docker-compose

# docker 그룹에 현재 계정을 등록하여 sudo 없이 docker 명령을 사용하게 함
sudo usermod -aG docker user
sudo service docker restart

# 새로운 터미널을 열고 확인
docker version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo usermod -aG docker user 에서 자신의 userName을 써야함!!!&lt;/p&gt;
&lt;pre id=&quot;code_1742870475919&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# docker version 확인
docker --version

# docker compose version 확인
docker-compose --version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 윈도우에 docker desktop 설치 후&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;686&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/otclF/btsMT6TXNrw/FJQOQNljVz4MWKgGnXdHkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/otclF/btsMT6TXNrw/FJQOQNljVz4MWKgGnXdHkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/otclF/btsMT6TXNrw/FJQOQNljVz4MWKgGnXdHkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FotclF%2FbtsMT6TXNrw%2FFJQOQNljVz4MWKgGnXdHkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;504&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;504&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;</description>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/155</guid>
      <comments>https://seungmin576.tistory.com/155#entry155comment</comments>
      <pubDate>Tue, 25 Mar 2025 09:53:44 +0900</pubDate>
    </item>
    <item>
      <title>@MappedSuperclass와 @AttributeOverrides, @AttributeOverride</title>
      <link>https://seungmin576.tistory.com/153</link>
      <description>&lt;pre id=&quot;code_1741943220083&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package org.example.expert.domain.common.entity;

import jakarta.persistence.*;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;

    @PrePersist
    public void onPrePersist() {    //생성시 나노초 저장안하기
        this.createdAt = createdAt.truncatedTo(ChronoUnit.SECONDS);
        this.modifiedAt = modifiedAt.truncatedTo(ChronoUnit.SECONDS);
    }

    @PreUpdate
    public void onPreUpdate() { //업뎃시 나노초 저장안하기
        this.modifiedAt = modifiedAt.truncatedTo(ChronoUnit.SECONDS);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 추상클래스가 있어서 다른 entity 클래스들에서 상속받아 편하게 생성시간과 수정시간을 생성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 만약 어떤 클래스는 Timestamp 클래스를 상속 받더라도 수정시간은 필요없다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1741943283919&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package org.example.expert.domain.log.entity;

import jakarta.persistence.*;
import lombok.NoArgsConstructor;
import org.example.expert.domain.common.entity.Timestamped;
import org.springframework.http.HttpStatus;

@Entity
@NoArgsConstructor
@AttributeOverrides({
        @AttributeOverride(name = &quot;modifiedAt&quot;, column = @Column(insertable = false, updatable = false))
})
public class Log extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String message;

    @Enumerated(EnumType.STRING)
    private HttpStatus httpStatus;

    public Log(String message, HttpStatus httpStatus) {
        this.message = message;
        this.httpStatus = httpStatus;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 저장하는 entity 클래스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;log는 저장만 필요할뿐 수정을 할 이유는 전혀 없어서 modifiedAt이 전혀 필요없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굳이 Timestamped를 상속을 받으면서 modifiedAt을 저장하고 싶지 않다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@AttributeOverrides, @AttributeOverride를 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@AttributeOverrides와 @AttributeOverride는 JPA에서 사용하는 어노테이션으로, &lt;b&gt;엔티티 상속 관계에서 상속받은 속성의 매핑을 변경하거나 재정의할 때 사용&lt;/b&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;@AttributeOverride&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@AttributeOverride는 단일 속성을 재정의할 때 사용한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 들어, 상위 클래스의 필드 이름과 매핑 정보를 하위 클래스에서 다르게 지정하고 싶을 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1741943415655&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@AttributeOverride(name = &quot;속성_이름&quot;, column = @Column(새로운_속성_정보))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 Log 클래스에서는&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;@AttributeOverride(name&amp;nbsp;=&amp;nbsp;&quot;modifiedAt&quot;,&amp;nbsp;column&amp;nbsp;=&amp;nbsp;@Column(insertable&amp;nbsp;=&amp;nbsp;false,&amp;nbsp;updatable&amp;nbsp;=&amp;nbsp;false))&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;이런식으로 사용했는데 의미는 modifiedAt 필드의 속성을 생성과 업데이트가 불가능하게 Log 클래스에서 재정의한 것이다.&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;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@AttributeOverrides&lt;/b&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;span&gt;@AttributeOverrides는 여러 속성을 한꺼번에 재정의할 때 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; @AttributeOverride 어노테이션을 배열로 받아서 여러 속성을 재정의할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1741943761652&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@AttributeOverrides({
    @AttributeOverride(name = &quot;속성_이름1&quot;, column = @Column(새로운_속성_정보1)),
    @AttributeOverride(name = &quot;속성_이름2&quot;, column = @Column(새로운_속성_정보2))
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;사실 위 Log 클래스에서는 사용할 필요가 없었다.&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;
&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;Log 클래스에 적용한 결과&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rdycc/btsMLM1woXG/IiIc1kXOdCEA4POc0UCmT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rdycc/btsMLM1woXG/IiIc1kXOdCEA4POc0UCmT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rdycc/btsMLM1woXG/IiIc1kXOdCEA4POc0UCmT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frdycc%2FbtsMLM1woXG%2FIiIc1kXOdCEA4POc0UCmT1%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;605&quot; height=&quot;68&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;H2 데이터베이스이다. MODIFIED_AT이 null인걸 확인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저렇게 필드는 생기고 null로 저장되는데 만약 필드조차 생기게 하고 싶지 않다면 Timestamped 클래스를 상속 받는게 아니라 따로 코드로 작성해주는게 좋아 보인다.&lt;/p&gt;</description>
      <category>spring</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/153</guid>
      <comments>https://seungmin576.tistory.com/153#entry153comment</comments>
      <pubDate>Fri, 14 Mar 2025 18:16:25 +0900</pubDate>
    </item>
    <item>
      <title>질문할 것들</title>
      <link>https://seungmin576.tistory.com/152</link>
      <description>&lt;pre id=&quot;code_1741848856449&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package org.example.expert.config;

import lombok.RequiredArgsConstructor;
import org.example.expert.domain.user.enums.UserRole;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity  //웹 보안 지원을 활성화하고 Spring MVC 통합을 제공한다.
@EnableMethodSecurity(securedEnabled = true)    //@Secured, @PreAuthorize, @PostAuthorize 와 같은 메서드 레벨 보안 애노테이션을 활성화
public class SecurityConfig {
    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {  //스프링 시큐리티는 BCryptPasswordEncoder를 제공해준다. @Bean으로 등록해 사용한다.
        return new BCryptPasswordEncoder();
    }

//    @Bean
//    public WebSecurityCustomizer webSecurityCustomizer() {  //h2 웹 콘솔을 시큐리티가 막는 걸 무시하는 코드
//        return (web -&amp;gt; web.ignoring()
//                .requestMatchers(new AntPathRequestMatcher(&quot;/h2-console/**&quot;))
//        );
//    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session -&amp;gt; session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .addFilterBefore(jwtAuthenticationFilter, SecurityContextHolderAwareRequestFilter.class)
                .formLogin(AbstractHttpConfigurer::disable)//SSR이 아니기 때문에 폼 기반 로그인 기능이 필요하지 않으므로 비활성화한다. UsernamePasswordAuthenticationFilter, DefaultLoginPageGeneratingFilter 비활성화
                .anonymous(AbstractHttpConfigurer::disable)//익명 사용자 권한은 필요 없다.(인증은 JWT를 통해 이루어진다.) AnonymousAuthenticationFilter 비활성화
                .httpBasic(AbstractHttpConfigurer::disable)//커스텀 FIlter를 사용하므로 비활성화 한다. BasicAuthenticationFilter 비활성화
                .logout(AbstractHttpConfigurer::disable)//로그아웃은 세션 정보를 지우는 요청이다. 세션이 아니므로 비활성화 한다. LogoutFilter 비활성화
                .rememberMe(AbstractHttpConfigurer::disable)//StateLess이기 때문에 Remember를 할 수가 없다. RememberMeAuthenticationFilter 비활성화
                .authorizeHttpRequests(auth -&amp;gt; auth
                        .requestMatchers(request -&amp;gt; request.getRequestURI().startsWith(&quot;/auth&quot;)).permitAll()
                        .requestMatchers(&quot;/test&quot;).hasAuthority(UserRole.Authority.ADMIN)
                        .requestMatchers(&quot;/open&quot;).permitAll()
                        .requestMatchers(&quot;/h2-console/**&quot;).permitAll()
                        .anyRequest().authenticated()   //SecurityContext에 AbstractAuthenticationToken이 set이 되어 있다면 통과를 시키겠단 의미이다.
                )
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링시큐리티 사용하면서 h2 웹&amp;nbsp; 콘솔 허용하려고 할때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;securityFilterChain에 써넣은 코드(아래에 적은 코드)로는 허용이 안되는 이유 질문하기.&lt;/p&gt;
&lt;pre id=&quot;code_1741947176774&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;                        .requestMatchers(&quot;/h2-console/**&quot;).permitAll()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;h2-console 로 작성하면 아예 첫화면부터 403뜸.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;h2-console/** 하면 첫화면은 잘 뜨나 connect 하면&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;922&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bXCP/btsMKTeqFJI/VY4pqtpg4LORnsbFTIHhj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bXCP/btsMKTeqFJI/VY4pqtpg4LORnsbFTIHhj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bXCP/btsMKTeqFJI/VY4pqtpg4LORnsbFTIHhj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bXCP%2FbtsMKTeqFJI%2FVY4pqtpg4LORnsbFTIHhj1%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;922&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;922&quot;/&gt;&lt;/span&gt;&lt;/figure&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;</description>
      <category>오류, 기능, 문제해결(JAVA)</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/152</guid>
      <comments>https://seungmin576.tistory.com/152#entry152comment</comments>
      <pubDate>Thu, 13 Mar 2025 15:55:03 +0900</pubDate>
    </item>
    <item>
      <title>entity를 저장할때 LocalDateTime에서 초를 저장하지 않는 법</title>
      <link>https://seungmin576.tistory.com/151</link>
      <description>&lt;pre id=&quot;code_1741842909351&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package org.example.expert.domain.common.entity;

import jakarta.persistence.*;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime modifiedAt;

    @PrePersist
    public void onPrePersist() {
        this.createdAt = createdAt.truncatedTo(ChronoUnit.MINUTES);
        this.modifiedAt = modifiedAt.truncatedTo(ChronoUnit.MINUTES);
    }

    @PreUpdate
    public void onPreUpdate() {
        this.modifiedAt = modifiedAt.truncatedTo(ChronoUnit.MINUTES);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;40&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0i8EN/btsMJaBP878/uj6jPZzU47bXojsBgsNlTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0i8EN/btsMJaBP878/uj6jPZzU47bXojsBgsNlTk/img.png&quot; data-alt=&quot;위는 초를 저장한 것 아래는 코드를 추가하여 초를 저장하지 않은 것&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0i8EN/btsMJaBP878/uj6jPZzU47bXojsBgsNlTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0i8EN%2FbtsMJaBP878%2Fuj6jPZzU47bXojsBgsNlTk%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;627&quot; height=&quot;40&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;40&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;위는 초를 저장한 것 아래는 코드를 추가하여 초를 저장하지 않은 것&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@PrePersist&lt;/b&gt;와 &lt;b&gt;@PreUpdate&lt;/b&gt;는 JPA(EntityManager)에서 제공하는 콜백 메서드로, 엔티티가 영속성 컨텍스트에 추가되거나 업데이트되기 전에 특정 동작을 수행할 수 있게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 어노테이션들을 사용하면 엔티티가 저장되거나 업데이트되기 전에 수행해야 하는 로직을 정의할 수 있습니다. &lt;br /&gt;&lt;br /&gt;1. @PrePersist&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;엔티티가&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;처음&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;2. @PreUpdate: &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;nbsp;&amp;nbsp;- 이 어노테이션을 사용하여 엔티티가 업데이트되기 전에 수행해야 할 로직을 정의할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;ChronoUnit.MINUTES 대신 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;ChronoUnit.SECONDS를 사용했다면 초까지만 저장이 된다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>spring</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/151</guid>
      <comments>https://seungmin576.tistory.com/151#entry151comment</comments>
      <pubDate>Thu, 13 Mar 2025 14:17:08 +0900</pubDate>
    </item>
    <item>
      <title>h2 데이터베이스 스프링에서 테스트코드용으로 인메모리형식으로 사용할때</title>
      <link>https://seungmin576.tistory.com/150</link>
      <description>&lt;pre id=&quot;code_1741336514482&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;application.properties 파일을 테스트쪽에도 resources 패키지를 만들어 이런식으로 작성해 넣어준다.&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;spring.datasource.url=jdbc:h2:mem:testdb;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;h2 데이터베이스의 URL을 설정한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; DB_CLOSE_DELAY=-1 &lt;/b&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;DB_CLOSE_DELAY 설정은 데이터베이스가 언제 닫힐지를 제어한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-1 값은 어플리케이션이 실행되는 동안 데이터베이스가 계속 열려있도록 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; DATABASE_TO_UPPER=false&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB_CLOSE_ON_EXIT=FALSE&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&lt;span&gt;spring.datasource.driverClassName=org.h2.Driver&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; 데이터베이스 연결을 위한 드라이버 클래스 이름을 설정합니다. 여기서는 H2 데이터베이스를 사용하므로 org.h2.Driver를 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;spring.datasource.username=sa&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; 데이터베이스의 사용자 이름을 설정합니다. H2 데이터베이스의 기본 사용자 이름은 sa입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;spring.datasource.password=&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; 데이터베이스의 비밀번호를 설정합니다. H2 데이터베이스의 기본 비밀번호는 빈 문자열입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;spring.jpa.database-platform=org.hibernate.dialect.H2Dialect&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; JPA (Java Persistence API)에서 사용할 데이터베이스 방언(dialect)을 설정합니다. H2 데이터베이스를 사용하므로 org.hibernate.dialect.H2Dialect를 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;spring.jpa.hibernate.ddl-auto=create&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; 애플리케이션 시작 시 데이터베이스 스키마를 자동으로 생성하도록 설정합니다. create 옵션은 기존 스키마를 삭제하고 새로 생성합니다. (주의: 실제 운영 환경에서는 이 설정을 주의해서 사용해야 합니다)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;spring.jpa.show-sql=true&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;설명:&lt;/b&gt; Hibernate가 실행하는 SQL 쿼리를 콘솔에 출력하도록 설정합니다. 이는 디버깅과 개발에 유용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>SQL,Database</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/150</guid>
      <comments>https://seungmin576.tistory.com/150#entry150comment</comments>
      <pubDate>Fri, 7 Mar 2025 17:42:52 +0900</pubDate>
    </item>
    <item>
      <title>@WebMvcTest IllegalArgumentException: JPA metamodel must not be empty 오류 뜰때</title>
      <link>https://seungmin576.tistory.com/149</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 1: Configuration 설정 분리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@EnableJpaAuditing 설정을 별도의 Configuration 클래스로 분리하여 테스트 시 JPA 관련 빈들이 로드되지 않도록 합니다. 예를 들어:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;java&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Configuration
@EnableJpaAuditing
public class JpaConfig {
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 하면 테스트 코드 실행 시 Application이 JPA와 상관없이 정상 실행하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 2: MockBean 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;테스트 코드에 JpaMetamodelMappingContext 클래스를 @MockBean으로 추가합니다. 예를 들어:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;java&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@WebMvcTest(StoreController.class)
public class StoreControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private StoreService storeService;

    @MockBean
    private JwtUtil jwtUtil;

    @MockBean
    private JpaMetamodelMappingContext jpaMetamodelMappingContext;

    @Test
    void shouldFindStoreById() throws{
    
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;JpaMetamodelMappingContext&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;는 JPA 메타모델을 관리하는 컨텍스트입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 클래스는 JPA 엔티티와 메타모델 클래스 간의 매핑 정보를 유지하는 데 사용됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Spring Boot는 JPA를 사용할 때 이러한 메타모델 정보를 필요로 합니다.&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&gt;@WebMvcTest 어노테이션은 주로 컨트롤러 레이어만 테스트하기 위해 사용됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 테스트는 데이터베이스나 서비스 레이어를 실제로 로드하지 않고, 최소한의 웹 컨텍스트를 생성하여 빠르게 테스트를 실행할 수 있습니다. 그러나, JPA와 관련된 의존성이 없기 때문에, &lt;b&gt;JPA 메타모델을 인식하지 못해 IllegalArgumentException: JPA metamodel must not be empty 오류가 발생하게 됩니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@MockBean JpaMetamodelMappingContext를 추가하면, Spring이 JPA 메타모델 정보를 필요로 할 때, 실제 메타모델 대신 모킹된 빈을 사용하게 되어 오류를 회피할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이를 통해 다음과 같은 문제를 해결할 수 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;JPA 메타모델 부재&lt;/b&gt;: @WebMvcTest는 JPA 엔티티 및 메타모델 빈을 로드하지 않으므로, 메타모델이 비어 있는 상태가 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Mocking&lt;/b&gt;: JpaMetamodelMappingContext를 모킹하여 JPA 메타모델의 부재로 인한 예외를 피할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;따라서, JpaMetamodelMappingContext를 @MockBean으로 추가하면 Spring Boot가 이 클래스에 대한 의존성을 해결할 수 있게 되어 문제를 해결할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>spring</category>
      <author>seungmin576</author>
      <guid isPermaLink="true">https://seungmin576.tistory.com/149</guid>
      <comments>https://seungmin576.tistory.com/149#entry149comment</comments>
      <pubDate>Thu, 6 Mar 2025 22:02:15 +0900</pubDate>
    </item>
  </channel>
</rss>