<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title> 솜이노트</title>
    <link>https://somnote.tistory.com/</link>
    <description>개발 공부 일상기록 </description>
    <language>ko</language>
    <pubDate>Sun, 24 May 2026 13:06:02 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>뭉지맘</managingEditor>
    <image>
      <title> 솜이노트</title>
      <url>https://tistory1.daumcdn.net/tistory/6640167/attach/cd9baa1b3d6f4f0ea7d8bf1c0b7b2c76</url>
      <link>https://somnote.tistory.com</link>
    </image>
    <item>
      <title>#intelliJ(인텔리제이) 학생용 라이센스 기관확인 + 연장방법</title>
      <link>https://somnote.tistory.com/207</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;695&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ck0EFD/dJMcaibsUwL/LPiDFQ5WZWOyZBk5IRKagK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ck0EFD/dJMcaibsUwL/LPiDFQ5WZWOyZBk5IRKagK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ck0EFD/dJMcaibsUwL/LPiDFQ5WZWOyZBk5IRKagK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fck0EFD%2FdJMcaibsUwL%2FLPiDFQ5WZWOyZBk5IRKagK%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;271&quot; height=&quot;695&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;695&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인텔리제이 프로그램을 실행하여 Help - Register 을 선택하면 라이센스 남은 기간을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHW1kt/dJMcahQ8my1/QFG2I0eHKjxDYpupyftl10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHW1kt/dJMcahQ8my1/QFG2I0eHKjxDYpupyftl10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHW1kt/dJMcahQ8my1/QFG2I0eHKjxDYpupyftl10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHW1kt%2FdJMcahQ8my1%2FQFG2I0eHKjxDYpupyftl10%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;864&quot; height=&quot;469&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://account.jetbrains.com/licenses&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://account.jetbrains.com/licenses&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1773116399042&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;JetBrains Account&quot; data-og-description=&quot;&quot; data-og-host=&quot;account.jetbrains.com&quot; data-og-source-url=&quot;https://account.jetbrains.com/licenses&quot; data-og-url=&quot;https://account.jetbrains.com/login?authSessionId=61dd5003-c6a4-4c58-832d-abfc442d3b60&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://account.jetbrains.com/licenses&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://account.jetbrains.com/licenses&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;JetBrains Account&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;account.jetbrains.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;491&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEkJcq/dJMcahDAipi/JgnwJP7j7zsKtMnJefb5n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEkJcq/dJMcahDAipi/JgnwJP7j7zsKtMnJefb5n1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEkJcq/dJMcahDAipi/JgnwJP7j7zsKtMnJefb5n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEkJcq%2FdJMcahDAipi%2FJgnwJP7j7zsKtMnJefb5n1%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;491&quot; height=&quot;312&quot; data-origin-width=&quot;491&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이센스 종료일이 임박하면 Renew my Education Pack 하고 버튼이 있을것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클릭해서 갱신해주면&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C6ZDp/dJMcagdD3fY/PZKrNDUgPBiTv0ffKzptz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C6ZDp/dJMcagdD3fY/PZKrNDUgPBiTv0ffKzptz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C6ZDp/dJMcagdD3fY/PZKrNDUgPBiTv0ffKzptz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC6ZDp%2FdJMcagdD3fY%2FPZKrNDUgPBiTv0ffKzptz0%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;388&quot; height=&quot;25&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;25&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년이 추가로 늘어난 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> IDE/intelliJ</category>
      <category>인텔리제이 라이센스 갱신</category>
      <category>인텔리제이 라이센스 연장</category>
      <category>인텔리제이 라이센스 확인</category>
      <category>인텔리제이 학생용 연장</category>
      <category>학생용 라이센스 연장</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/207</guid>
      <comments>https://somnote.tistory.com/207#entry207comment</comments>
      <pubDate>Tue, 10 Mar 2026 13:34:14 +0900</pubDate>
    </item>
    <item>
      <title># Tomcat - tcnative-1.dill: Can't load IA 32-bit .dll on a AMD 64-bit platform 해결방법</title>
      <link>https://somnote.tistory.com/206</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Itkr8/dJMcabcagFf/puQQhnWTvrLhNvLgVXa5k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Itkr8/dJMcabcagFf/puQQhnWTvrLhNvLgVXa5k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Itkr8/dJMcabcagFf/puQQhnWTvrLhNvLgVXa5k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FItkr8%2FdJMcabcagFf%2FpuQQhnWTvrLhNvLgVXa5k0%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;415&quot; height=&quot;258&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;448&quot; data-start=&quot;289&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;344&quot; data-start=&quot;289&quot;&gt;OS/프로세스가 64-bit로 실행 중(&amp;ldquo;on a AMD 64-bit platform!&amp;rdquo; 문구)&lt;/li&gt;
&lt;li data-end=&quot;396&quot; data-start=&quot;345&quot;&gt;Tomcat이 tcnative-1.dll(Tomcat Native)을 로드하려고 시도&lt;/li&gt;
&lt;li data-end=&quot;448&quot; data-start=&quot;397&quot;&gt;그런데 해당 DLL이 32-bit(&amp;ldquo;Can&amp;rsquo;t load IA 32-bit .dll &amp;hellip;&amp;rdquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;478&quot; data-start=&quot;450&quot; data-ke-size=&quot;size16&quot;&gt;즉, 비트수(32/64)가 안 맞아서 실패한 경우입니다.&lt;/p&gt;
&lt;p data-end=&quot;478&quot; data-start=&quot;450&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;478&quot; data-start=&quot;450&quot; data-ke-size=&quot;size16&quot;&gt;로그에 나와있는 경로에 tcnative-1.dll 파일을 64bit 파일로 바꿔주면 해결됩니다.&lt;/p&gt;
&lt;p data-end=&quot;478&quot; data-start=&quot;450&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;478&quot; data-start=&quot;450&quot; 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;419&quot; data-origin-height=&quot;463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfSJtR/dJMcajnGrhZ/r563xlpNYcV6ZfCNLdFJ21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfSJtR/dJMcajnGrhZ/r563xlpNYcV6ZfCNLdFJ21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfSJtR/dJMcajnGrhZ/r563xlpNYcV6ZfCNLdFJ21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfSJtR%2FdJMcajnGrhZ%2Fr563xlpNYcV6ZfCNLdFJ21%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;419&quot; height=&quot;463&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;463&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771895818261&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;Index of /dist/tomcat/tomcat-connectors/native&quot; data-og-description=&quot;&quot; data-og-host=&quot;archive.apache.org&quot; data-og-source-url=&quot;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&quot; data-og-url=&quot;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://archive.apache.org/dist/tomcat/tomcat-connectors/native/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Index of /dist/tomcat/tomcat-connectors/native&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;archive.apache.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사이트에서 알맞은 버전에 binary파일을 다운하면 해당 위치에 64비트 파일이 함께 들어있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pKVb7/dJMcadHM0rA/eXEEP140m9oDKnxRO3nGKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pKVb7/dJMcadHM0rA/eXEEP140m9oDKnxRO3nGKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pKVb7/dJMcadHM0rA/eXEEP140m9oDKnxRO3nGKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpKVb7%2FdJMcadHM0rA%2FeXEEP140m9oDKnxRO3nGKK%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;464&quot; height=&quot;207&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 64비트 파일로 변경해주면 해결됩니다.&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> ️ 백엔드/ ️ Server</category>
      <category>.dll 32비트 64비트</category>
      <category>Apache Tomcat Native 라이브러리를 로드하지 못했습니다.</category>
      <category>tcnative-1.dll</category>
      <category>tcnative-1.dll에러</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/206</guid>
      <comments>https://somnote.tistory.com/206#entry206comment</comments>
      <pubDate>Tue, 24 Feb 2026 10:19:44 +0900</pubDate>
    </item>
    <item>
      <title># JS - Array.from()사용, NodeList와 배열의 차이</title>
      <link>https://somnote.tistory.com/205</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;querySelectorAll() 은 &lt;b&gt;배열처럼 보이지만 &amp;ldquo;배열이 아니다.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 map(), filter() 같은 배열 전용 메서드를 쓸 수 없다.&amp;nbsp;Array.from() 으로 &lt;b&gt;진짜 배열로 변환하는 과정이 필요하다.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1) querySelectorAll()의 반환값은 &amp;ldquo;NodeList&amp;rdquo;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;pre id=&quot;code_1765496802969&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const checked = document.querySelectorAll(&quot;.row-check:checked&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;checked 는 배열이 아니다.&lt;br /&gt;정확한 타입은 &lt;b&gt;NodeList&lt;/b&gt; 라는 &amp;ldquo;유사배열 객체&amp;rdquo;.&lt;/p&gt;
&lt;p data-end=&quot;444&quot; data-start=&quot;437&quot; data-ke-size=&quot;size16&quot;&gt;유사배열이란:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;495&quot; data-start=&quot;446&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;463&quot; data-start=&quot;446&quot;&gt;길이(length) 있음&lt;/li&gt;
&lt;li data-end=&quot;478&quot; data-start=&quot;464&quot;&gt;인덱스로 접근 가능&lt;/li&gt;
&lt;li data-end=&quot;495&quot; data-start=&quot;479&quot;&gt;여러 요소를 담고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;497&quot; data-ke-size=&quot;size16&quot;&gt;하지만,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;559&quot; data-start=&quot;503&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;519&quot; data-start=&quot;503&quot;&gt;&lt;b&gt;map() 없음&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;539&quot; data-start=&quot;520&quot;&gt;&lt;b&gt;filter() 없음&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;559&quot; data-start=&quot;540&quot;&gt;&lt;b&gt;reduce() 없음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;582&quot; data-start=&quot;561&quot; data-ke-size=&quot;size16&quot;&gt;즉, 배열처럼 생겼지만 배열이 아니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;582&quot; data-start=&quot;561&quot; data-ke-size=&quot;size26&quot;&gt;2) NodeList와 배열(Array)의 차이&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;특징&lt;/td&gt;
&lt;td&gt;NodeList&lt;/td&gt;
&lt;td&gt;Array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;length 있음&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인덱스로 접근&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;map(), filter() 사용&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push(), pop() 사용&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;진짜 배열?&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-end=&quot;798&quot; data-start=&quot;796&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;p data-end=&quot;833&quot; data-start=&quot;800&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NodeList = 배열처럼 보이지만 기능이 제한됨.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;833&quot; data-start=&quot;800&quot; data-ke-size=&quot;size26&quot;&gt;3) 그럼 왜 Array.from()을 쓰냐?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 쓸 수 없는 NodeList를&lt;br /&gt;&lt;b&gt;완전한 배열(Array)로 변환하기 위해서.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1765496900945&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const arr = Array.from(checked);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;985&quot; data-start=&quot;965&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이제 arr은 진짜 배열이 된다.&lt;/p&gt;
&lt;p data-end=&quot;991&quot; data-start=&quot;987&quot; data-ke-size=&quot;size16&quot;&gt;그러면:&lt;/p&gt;
&lt;pre id=&quot;code_1765496926800&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;arr.map(...)
arr.filter(...)
arr.reduce(...)&lt;/code&gt;&lt;/pre&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-end=&quot;1647&quot; data-start=&quot;1598&quot; data-ke-size=&quot;size16&quot;&gt;✔ querySelectorAll &amp;rarr; NodeList(유사배열, map 없음)&lt;/p&gt;
&lt;p data-end=&quot;1687&quot; data-start=&quot;1648&quot; data-ke-size=&quot;size16&quot;&gt;✔ Array.from(NodeList) &amp;rarr; 진짜 Array&lt;/p&gt;
&lt;p data-end=&quot;1718&quot; data-start=&quot;1688&quot; data-ke-size=&quot;size16&quot;&gt;✔ Array.map(el &amp;rArr; &amp;hellip; ) 사용 가능&lt;/p&gt;
&lt;p data-end=&quot;1735&quot; data-start=&quot;1720&quot; data-ke-size=&quot;size16&quot;&gt;그래서 순서가 이렇게 된다:&lt;/p&gt;
&lt;pre id=&quot;code_1765496984792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const checked = document.querySelectorAll(&quot;.row-check:checked&quot;);  
// NodeList

const ids = Array.from(checked).map(el =&amp;gt; el.dataset.id);
// Array &amp;rarr; id 배열 생성&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ️ 프론트엔드/ JS, React</category>
      <category>arrayfrom</category>
      <category>DOM조작</category>
      <category>Frontend</category>
      <category>javascript</category>
      <category>js문법</category>
      <category>NodeList</category>
      <category>개발자블로그</category>
      <category>웹개발</category>
      <category>자바스크립트배열</category>
      <category>코딩팁</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/205</guid>
      <comments>https://somnote.tistory.com/205#entry205comment</comments>
      <pubDate>Fri, 12 Dec 2025 08:52:27 +0900</pubDate>
    </item>
    <item>
      <title># JS - debounce() 함수 완전 정리</title>
      <link>https://somnote.tistory.com/204</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발하면서 디바운스 함수를 접해보신 적 있나요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크롤, 검색창 입력, 윈도우 리사이즈처럼 &lt;b&gt;짧은 시간에 반복해서 호출되는 이벤트를 일정 시간 동안 모아서 한 번만 실행&lt;/b&gt;하도록 하는 기술입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;debounce()란?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;일정 시간 동안 이벤트가 반복 발생해도, 마지막 호출만 실행되게 하는 함수 제어 기법&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 검색창에 글자를 입력할 때마다 API를 호출하면 서버가 과부하가 걸릴 수 있어요.&lt;br /&gt;이때 debounce()를 사용하면 &lt;b&gt;입력이 멈춘 후 특정 시간(예: 300ms)이 지나면 딱 한 번 API를 호출&lt;/b&gt;하게 만들 수 있어요.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;debounce()가 필요한 상황&lt;/h3&gt;
&lt;p data-end=&quot;594&quot; data-start=&quot;563&quot; data-ke-size=&quot;size16&quot;&gt;다음과 같이 &amp;ldquo;너무 자주 실행되는 이벤트&amp;rdquo;에서 필요합니다. :&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;719&quot; data-start=&quot;596&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;618&quot; data-start=&quot;596&quot;&gt;&lt;b&gt;실시간 검색 API 호출&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;640&quot; data-start=&quot;619&quot;&gt;&lt;b&gt;윈도우 리사이즈 이벤트&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;678&quot; data-start=&quot;641&quot;&gt;&lt;b&gt;스크롤 이벤트(무한 스크롤, 스크롤 위치 저장 등)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;698&quot; data-start=&quot;679&quot;&gt;&lt;b&gt;입력 폼 자동 저장&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;719&quot; data-start=&quot;699&quot;&gt;&lt;b&gt;버튼 중복 클릭 방지&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;debounce() 기본 동작 방식 요약&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;781&quot; data-start=&quot;756&quot;&gt;이벤트가 발생하면 &lt;b&gt;타이머를 초기화&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;820&quot; data-start=&quot;782&quot;&gt;일정 시간 동안 추가 이벤트가 들어오면 &lt;b&gt;기존 타이머 취소&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;856&quot; data-start=&quot;821&quot;&gt;마지막 이벤트가 들어온 후 &lt;b&gt;지정 시간 지난 뒤 실행&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, &quot;보다가 멈추면 실행&quot; 구조!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;가장 많이 쓰는 debounce 코드&amp;nbsp;&lt;/h2&gt;
&lt;pre id=&quot;code_1765341645730&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function debounce(func, delay) {
    let timer;

    return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() =&amp;gt; {
            func.apply(this, args);
        }, delay);
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 예제 1 &amp;mdash; 검색창 API 호출 제어&lt;/h3&gt;
&lt;pre id=&quot;code_1765341659953&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const search = debounce(function (keyword) {
    console.log(&quot;API 호출:&quot;, keyword);
}, 300);

document.querySelector(&quot;#search&quot;).addEventListener(&quot;input&quot;, (e) =&amp;gt; {
    search(e.target.value);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;효과:&lt;/b&gt;&lt;br /&gt;사용자가 빠르게 타이핑해도 API는 입력이 멈춘 후 단 한 번 실행됨.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용 예제 2 &amp;mdash; 스크롤 이벤트 최적화&lt;/h3&gt;
&lt;pre id=&quot;code_1765341707448&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function handleScroll() {
    console.log(&quot;스크롤 위치:&quot;, window.scrollY);
}

window.addEventListener(&quot;scroll&quot;, debounce(handleScroll, 200));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크롤은 엄청나게 많이 실행되기 때문에 디바운스로 CPU 부담을 줄일 수 있습니다.&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; throttle과 debounce 차이&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1897&quot; data-start=&quot;1764&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;개념&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;동작&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;원리&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1855&quot; data-start=&quot;1812&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1827&quot; data-start=&quot;1812&quot;&gt;&lt;b&gt;debounce&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;1845&quot; data-start=&quot;1827&quot; data-col-size=&quot;sm&quot;&gt;입력이 멈춘 뒤 한 번 실행&lt;/td&gt;
&lt;td data-end=&quot;1855&quot; data-start=&quot;1845&quot; data-col-size=&quot;sm&quot;&gt;검색창 입력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1897&quot; data-start=&quot;1856&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1871&quot; data-start=&quot;1856&quot;&gt;&lt;b&gt;throttle&lt;/b&gt;&lt;/td&gt;
&lt;td data-end=&quot;1884&quot; data-start=&quot;1871&quot; data-col-size=&quot;sm&quot;&gt;일정 간격마다 실행&lt;/td&gt;
&lt;td data-end=&quot;1897&quot; data-start=&quot;1884&quot; data-col-size=&quot;sm&quot;&gt;스크롤 위치 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 다 이벤트 제어지만 목적과 타이밍이 다릅니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;1939&quot; data-start=&quot;1932&quot; data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2082&quot; data-start=&quot;1941&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1986&quot; data-start=&quot;1941&quot;&gt;debounce()는 &lt;b&gt;연속된 호출을 묶어서 마지막 호출만 실행&lt;/b&gt;한다.&lt;/li&gt;
&lt;li data-end=&quot;2022&quot; data-start=&quot;1987&quot;&gt;타이핑, 스크롤, 리사이즈 등 &lt;b&gt;이벤트 최적화&lt;/b&gt;에 필수.&lt;/li&gt;
&lt;li data-end=&quot;2053&quot; data-start=&quot;2023&quot;&gt;setTimeout을 이용해 간단히 구현 가능.&lt;/li&gt;
&lt;li data-end=&quot;2082&quot; data-start=&quot;2054&quot;&gt;throttle과의 차이까지 알아두면 더 확실!&lt;/li&gt;
&lt;/ul&gt;</description>
      <category> ️ 프론트엔드/ JS, React</category>
      <category>debounce 함수</category>
      <category>javascript</category>
      <category>디바운스</category>
      <category>스크롤 성능 개선</category>
      <category>실시간 검색 구현</category>
      <category>웹 성능 최적화</category>
      <category>이벤트 최적화</category>
      <category>입력 지연 처리</category>
      <category>프론트엔드 개발</category>
      <category>함수 제어 기법</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/204</guid>
      <comments>https://somnote.tistory.com/204#entry204comment</comments>
      <pubDate>Wed, 10 Dec 2025 13:43:26 +0900</pubDate>
    </item>
    <item>
      <title># click up(클릭업) - Description(설명란)에 자주쓰이는 명령어 서식 단축키 모음</title>
      <link>https://somnote.tistory.com/203</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ClickUp의 Description 창은 마크다운(Markdown) 기반 + 자체 단축키를 지원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 자주 쓰이는 명령어, 서식, 단축키 모음입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 제목 / 헤딩 (Heading)&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;기능&lt;/td&gt;
&lt;td&gt;단축키&lt;/td&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제목 1&lt;/td&gt;
&lt;td&gt;# 공백&lt;/td&gt;
&lt;td&gt;# 제목&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제목 2&lt;/td&gt;
&lt;td&gt;## 공백&lt;/td&gt;
&lt;td&gt;## 소제목&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제목 3&lt;/td&gt;
&lt;td&gt;### 공백&lt;/td&gt;
&lt;td&gt;### 내용 구분&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 굵게 / 기울임 / 취소선&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;기능&lt;/td&gt;
&lt;td&gt;단축키&lt;/td&gt;
&lt;td&gt;문법&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;굵게&lt;/td&gt;
&lt;td&gt;Ctrl + B&lt;/td&gt;
&lt;td&gt;**텍스트**&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;기울임&lt;/td&gt;
&lt;td&gt;Ctrl + I&lt;/td&gt;
&lt;td&gt;*텍스트*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;취소선&lt;/td&gt;
&lt;td&gt;~~텍스트~~&lt;/td&gt;
&lt;td&gt;~~삭제~~&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 리스트&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 불릿 리스트&lt;/h3&gt;
&lt;pre id=&quot;code_1765253261127&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- 아이템
- 아이템&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 번호 리스트&lt;/h3&gt;
&lt;pre id=&quot;code_1765253286710&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. 첫 번째
2. 두 번째
3. 세 번째&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 체크박스(To-do)&lt;/h2&gt;
&lt;pre id=&quot;code_1765253305510&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- [ ] 할 일
- [x] 완료된 일&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 코드 블록 (개발자용 문서 작성할 때 필수)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인라인 코드&lt;/h3&gt;
&lt;pre id=&quot;code_1765253349477&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;`코드`&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블록 코드&lt;/h3&gt;
&lt;pre id=&quot;code_1765253367342&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;```언어
내용
```&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 인용문 (Quote)&lt;/h2&gt;
&lt;pre id=&quot;code_1765253388470&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; 인용문 혹은 강조하고 싶은 말&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 구분선&lt;/h2&gt;
&lt;pre id=&quot;code_1765253400541&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. Slash Commands (/ 명령어)&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 231px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;명렁어&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/h1, /h2, /h3&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;제목&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/divider&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;구분선&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/table&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;표&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/bulleted list&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;리스트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/numbered list&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;번호 리스트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/code&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;코드 블록&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/quote&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;인용문&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/embed&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Embed 삽입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/image&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;이미지 삽입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;/mention&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;유저 언급&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-end=&quot;1886&quot; data-start=&quot;1781&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1886&quot; data-start=&quot;1781&quot; data-ke-size=&quot;size16&quot;&gt;위 서식들을 즐겨찾기처럼 저장해두면 업무 문서, 회의록, 개발 정리까지 훨씬 효율적으로 작성할 수 있게됩니다.&lt;/p&gt;</description>
      <category>  잡동사니</category>
      <category>ClickUp 단축키</category>
      <category>ClickUp 마크다운</category>
      <category>ClickUp 사용법</category>
      <category>ClickUp 설명란 작성법</category>
      <category>ClickUp 템플릿</category>
      <category>생산성 툴 추천</category>
      <category>업무 자동화</category>
      <category>업무 효율화 방법</category>
      <category>프로젝트 관리 툴 추천</category>
      <category>협업툴 비교</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/203</guid>
      <comments>https://somnote.tistory.com/203#entry203comment</comments>
      <pubDate>Tue, 9 Dec 2025 13:13:53 +0900</pubDate>
    </item>
    <item>
      <title># FCM Token 기반 푸시 알림 구현 (Expo + Spring Boot For Android)</title>
      <link>https://somnote.tistory.com/202</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React Native(Expo) 앱에서 푸시 알림을 구현하려면&lt;br /&gt;&lt;b&gt;Firebase Cloud Messaging(FCM)&lt;/b&gt; 을 사용하는 것이 가장 안정적인 구조다.&lt;br /&gt;여기서는 ExpoPushToken이 아닌 &lt;b&gt;FCM Token 기반&lt;/b&gt;으로 푸시를 구현하는 전체 흐름을 정리한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;414&quot; data-start=&quot;395&quot; data-ke-size=&quot;size26&quot;&gt;1. Firebase 기본 설정&lt;/h2&gt;
&lt;h4 data-end=&quot;438&quot; data-start=&quot;416&quot; data-ke-size=&quot;size20&quot;&gt;1) Firebase 프로젝트 생성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://firebase.google.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://firebase.google.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1764826314128&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;Firebase | Google's Mobile and Web App Development Platform&quot; data-og-description=&quot;개발자가 사용자가 좋아할 만한 앱과 게임을 빌드하도록 지원하는 Google의 모바일 및 웹 앱 개발 플랫폼인 Firebase에 대해 알아보세요.&quot; data-og-host=&quot;firebase.google.com&quot; data-og-source-url=&quot;https://firebase.google.com/&quot; data-og-url=&quot;https://firebase.google.com/?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bSL3yN/hyZOFuoJkR/tjwhKLtBws3i6bJ2AJKPt1/img.png?width=1600&amp;amp;height=800&amp;amp;face=0_0_1600_800,https://scrap.kakaocdn.net/dn/dbFjiP/hyZO58rpDP/lV3Cx0f4KlRoQiE0MJkcnk/img.png?width=1600&amp;amp;height=800&amp;amp;face=0_0_1600_800&quot;&gt;&lt;a href=&quot;https://firebase.google.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://firebase.google.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bSL3yN/hyZOFuoJkR/tjwhKLtBws3i6bJ2AJKPt1/img.png?width=1600&amp;amp;height=800&amp;amp;face=0_0_1600_800,https://scrap.kakaocdn.net/dn/dbFjiP/hyZO58rpDP/lV3Cx0f4KlRoQiE0MJkcnk/img.png?width=1600&amp;amp;height=800&amp;amp;face=0_0_1600_800');&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;Firebase | Google's Mobile and Web App Development Platform&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발자가 사용자가 좋아할 만한 앱과 게임을 빌드하도록 지원하는 Google의 모바일 및 웹 앱 개발 플랫폼인 Firebase에 대해 알아보세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;firebase.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-end=&quot;467&quot; data-start=&quot;439&quot; data-ke-size=&quot;size16&quot;&gt;Firebase Console &amp;rarr; 새 프로젝트 생성&lt;/p&gt;
&lt;p data-end=&quot;476&quot; data-start=&quot;469&quot; data-ke-size=&quot;size16&quot;&gt;필요한 기능:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;521&quot; data-start=&quot;477&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;494&quot; data-start=&quot;477&quot;&gt;Cloud Messaging&lt;/li&gt;
&lt;li data-end=&quot;521&quot; data-start=&quot;495&quot;&gt;Firebase Admin SDK (백엔드)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-end=&quot;544&quot; data-start=&quot;528&quot; data-ke-size=&quot;size20&quot;&gt;2) Android 설정&lt;/h4&gt;
&lt;p data-end=&quot;577&quot; data-start=&quot;546&quot; data-ke-size=&quot;size16&quot;&gt;Android 앱 추가 &amp;rarr; 패키지명 입력&lt;br /&gt;경로 예시:&lt;/p&gt;
&lt;pre id=&quot;code_1764825930621&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;com.appname.app&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 제공되는 파일을 다운로드:&lt;/p&gt;
&lt;pre id=&quot;code_1764825942981&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;google-services.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Expo(EAS)에서는 다음처럼 app.json 또는 app.config.js에 등록해준다:&lt;/p&gt;
&lt;pre id=&quot;code_1764825952789&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;expo&quot;: {
    &quot;android&quot;: {
      &quot;googleServicesFile&quot;: &quot;./google-services.json&quot;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. FCM Token 가져오기 (Expo 앱)&lt;/h2&gt;
&lt;p data-end=&quot;1297&quot; data-start=&quot;1223&quot; data-ke-size=&quot;size16&quot;&gt;Expo Go에서는 FCM Token이 생성되지 않기 때문에&lt;br /&gt;&lt;b&gt;반드시 EAS Build로 만든 독립 앱&lt;/b&gt;에서 테스트해야 한다.&lt;/p&gt;
&lt;p data-end=&quot;1316&quot; data-start=&quot;1299&quot; data-ke-size=&quot;size16&quot;&gt;앱에서 토큰을 가져오는 API:&lt;/p&gt;
&lt;pre id=&quot;code_1764826036820&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import * as Notifications from &quot;expo-notifications&quot;;

const tokenInfo = await Notifications.getDevicePushTokenAsync();
const fcmToken = tokenInfo.data;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 받아온 FCM Token을 백엔드에 저장해야 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 백엔드(Firebase Admin SDK) 설정&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) Admin SDK 설치&lt;/h4&gt;
&lt;p data-end=&quot;1744&quot; data-start=&quot;1688&quot; data-ke-size=&quot;size16&quot;&gt;Firebase Console&lt;br /&gt;&amp;rarr; 프로젝트 설정&lt;br /&gt;&amp;rarr; 서비스 계정&lt;br /&gt;&amp;rarr; &amp;ldquo;새 비공개 키 생성&amp;rdquo;&lt;/p&gt;
&lt;p data-end=&quot;1752&quot; data-start=&quot;1746&quot; data-ke-size=&quot;size16&quot;&gt;파일명 예:&lt;/p&gt;
&lt;pre id=&quot;code_1764826106549&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bimong-firebase-adminsdk-xxxx.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 리소스 폴더 또는 Docker 컨테이너 내에 넣은 후&lt;br /&gt;application.properties에서 경로 설정:&lt;/p&gt;
&lt;pre id=&quot;code_1764826126373&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;firebase.service-account=/app/config/firebase-service-account.json&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) FirebaseApp 초기화&lt;/h4&gt;
&lt;pre id=&quot;code_1764826150716&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class FirebaseConfig {

    @Value(&quot;${firebase.service-account}&quot;)
    private String serviceAccountPath;

    @PostConstruct
    public void init() throws IOException {
        FileInputStream serviceAccount = new FileInputStream(serviceAccountPath);

        FirebaseOptions options = FirebaseOptions.builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .build();

        if (FirebaseApp.getApps().isEmpty()) {
            FirebaseApp.initializeApp(options);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 백엔드에서 FCM으로 푸시 보내기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 메시지 DTO&lt;/h4&gt;
&lt;pre id=&quot;code_1764826182765&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class PushMessageDTO {
    private String token;
    private String title;
    private String body;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 메시지 전송 서비스&lt;/h4&gt;
&lt;pre id=&quot;code_1764826204427&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class FcmService {

    public void sendMessage(PushMessageDTO dto) throws Exception {

        Message message = Message.builder()
                .setToken(dto.getToken())
                .setNotification(
                        Notification.builder()
                                .setTitle(dto.getTitle())
                                .setBody(dto.getBody())
                                .build()
                )
                .build();

        String response = FirebaseMessaging.getInstance().send(message);
        System.out.println(&quot;FCM 응답: &quot; + response);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FirebaseMessaging은 FCM v1 API 기반으로 작동한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;3421&quot; data-start=&quot;3408&quot; data-ke-size=&quot;size26&quot;&gt;5. 실제 동작 흐름&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;3643&quot; data-start=&quot;3423&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;3447&quot; data-start=&quot;3423&quot;&gt;앱 실행 &amp;rarr; FCM Token 발급&lt;/li&gt;
&lt;li data-end=&quot;3467&quot; data-start=&quot;3448&quot;&gt;앱이 토큰을 백엔드로 전송&lt;/li&gt;
&lt;li data-end=&quot;3503&quot; data-start=&quot;3468&quot;&gt;백엔드 DB에 deviceId + fcmToken 저장&lt;/li&gt;
&lt;li data-end=&quot;3539&quot; data-start=&quot;3504&quot;&gt;스케줄러나 특정 비즈니스 로직에서 fcmToken 조회&lt;/li&gt;
&lt;li data-end=&quot;3580&quot; data-start=&quot;3540&quot;&gt;Firebase Admin SDK &amp;rarr; FCM 서버에 메시지 전송&lt;/li&gt;
&lt;li data-end=&quot;3617&quot; data-start=&quot;3581&quot;&gt;FCM 서버 &amp;rarr; 기기(iOS/Android)로 알림 전달&lt;/li&gt;
&lt;li data-end=&quot;3643&quot; data-start=&quot;3618&quot;&gt;앱이 백그라운드/꺼진 상태여도 알림 수신&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;3962&quot; data-start=&quot;3955&quot; data-ke-size=&quot;size26&quot;&gt;6. 정리&lt;/h2&gt;
&lt;p data-end=&quot;3980&quot; data-start=&quot;3964&quot; data-ke-size=&quot;size16&quot;&gt;푸시가 정상적으로 동작하려면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;4128&quot; data-start=&quot;3982&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;4014&quot; data-start=&quot;3982&quot;&gt;Firebase Cloud Messaging 설정&lt;/li&gt;
&lt;li data-end=&quot;4061&quot; data-start=&quot;4015&quot;&gt;google-services.json / plist 포함된 EAS 앱 빌드&lt;/li&gt;
&lt;li data-end=&quot;4083&quot; data-start=&quot;4062&quot;&gt;앱에서 FCM Token 발급&lt;/li&gt;
&lt;li data-end=&quot;4096&quot; data-start=&quot;4084&quot;&gt;백엔드에 저장&lt;/li&gt;
&lt;li data-end=&quot;4128&quot; data-start=&quot;4097&quot;&gt;백엔드에서 Firebase Admin SDK로 푸시&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;4158&quot; data-start=&quot;4130&quot; data-ke-size=&quot;size16&quot;&gt;이 구조가 완성돼야 기기에서 푸시가 정상 동작한다&lt;/p&gt;</description>
      <category> ️ 백엔드/☕JAVA</category>
      <category>Android 푸시알림</category>
      <category>Expo FCM</category>
      <category>Expo Notification</category>
      <category>FCM Token 구현</category>
      <category>Firebase Cloud Messaging</category>
      <category>iOS 푸시 설정</category>
      <category>React Native</category>
      <category>spring boot firebase</category>
      <category>모바일 알림 개발</category>
      <category>백엔드 푸시 서버</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/202</guid>
      <comments>https://somnote.tistory.com/202#entry202comment</comments>
      <pubDate>Thu, 4 Dec 2025 14:32:47 +0900</pubDate>
    </item>
    <item>
      <title># JAVA - 메일로 임시 비밀번호 발급하는 방법 (Gmail SMTP)</title>
      <link>https://somnote.tistory.com/201</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;메일로 임시 비밀번호를 발급하려면 일단 SMTP를 사용해야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;저는 구글로 해당 기능을 사용해 보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Gmail SMTP&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Gmail SMTP를 사용하려면 아래 3가지를 충족해야 합니다.&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 data-end=&quot;268&quot; data-start=&quot;230&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;구글 계정이 2단계 인증(OTP) 활성화되어 있을 것&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;306&quot; data-start=&quot;269&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;앱 비밀번호(App Password)를 발급받을 것&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;370&quot; data-start=&quot;307&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;Spring Boot 메일 설정(application.properties)이 SMTP 규칙에 맞을 것&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;필요한 사전 조건&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;456&quot; data-start=&quot;427&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1) 구글 계정에서 2단계 인증 활성화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;514&quot; data-start=&quot;457&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;링크: &lt;a href=&quot;https://support.google.com/accounts/answer/185839?hl=ko&amp;amp;co=GENIE.Platform%3DAndroid&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://support.google.com/accounts/answer/185839?hl=ko&amp;amp;co=GENIE.Platform%3DAndroid&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;rarr; &amp;ldquo;2단계 인증&amp;rdquo; 켜기&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1764728427074&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;2단계 인증 사용 - Android - Google 계정 고객센터&quot; data-og-description=&quot;2단계 인증을 사용하면 비밀번호가 도용되는 경우에 대비하여 계정 보안을 한층 강화할 수 있습니다. 2단계 인증을 설정한 후에는 다음을 사용하여 계정에 로그인할 수 있습니다. 비밀번호 및 2&quot; data-og-host=&quot;support.google.com&quot; data-og-source-url=&quot;https://support.google.com/accounts/answer/185839?hl=ko&amp;amp;co=GENIE.Platform%3DAndroid&quot; data-og-url=&quot;https://support.google.com/accounts/answer/185839?co=GENIE.Platform%3DAndroid&amp;amp;hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://support.google.com/accounts/answer/185839?hl=ko&amp;amp;co=GENIE.Platform%3DAndroid&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://support.google.com/accounts/answer/185839?hl=ko&amp;amp;co=GENIE.Platform%3DAndroid&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;2단계 인증 사용 - Android - Google 계정 고객센터&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2단계 인증을 사용하면 비밀번호가 도용되는 경우에 대비하여 계정 보안을 한층 강화할 수 있습니다. 2단계 인증을 설정한 후에는 다음을 사용하여 계정에 로그인할 수 있습니다. 비밀번호 및 2&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;support.google.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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2) App Password 발급&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2단계 인증을 켠 뒤에 아래 메뉴가 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mEZJO/dJMcaiaJszu/GkleGaFUcttxEagKdSRUjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mEZJO/dJMcaiaJszu/GkleGaFUcttxEagKdSRUjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mEZJO/dJMcaiaJszu/GkleGaFUcttxEagKdSRUjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmEZJO%2FdJMcaiaJszu%2FGkleGaFUcttxEagKdSRUjK%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;763&quot; height=&quot;201&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;658&quot; data-start=&quot;613&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;624&quot; data-start=&quot;613&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;앱: Mail&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;658&quot; data-start=&quot;625&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;기기: 원하는 이름(예: SpringBootServer)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;708&quot; data-start=&quot;660&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;rarr; 16자리 비밀번호가 생성됨&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;rarr; 이 코드가 &lt;b&gt;SMTP 비밀번호&lt;/b&gt; 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;전체 구성&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;(1) application.properties 설정&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1764728611734&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your_email@gmail.com
spring.mail.password=발급받은_앱_비밀번호
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;(2) 의존성 추가 (build.gradle)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1764728796270&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation 'org.springframework.boot:spring-boot-starter-mail'&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;(3) 템플릿 메일 발송 임시 코드&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;360&quot; data-start=&quot;293&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JavaMailSender + MimeMessageHelper를 이용해 HTML 형식으로 전달해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;394&quot; data-start=&quot;361&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;변수를 템플릿에 바인딩하는 로직이 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1764728866734&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;body style=&quot;font-family: Arial;&quot;&amp;gt;

    &amp;lt;h2 th:text=&quot;${title}&quot;&amp;gt;메일 제목&amp;lt;/h2&amp;gt;

    &amp;lt;p th:text=&quot;${message}&quot;&amp;gt;기본 메시지&amp;lt;/p&amp;gt;

    &amp;lt;div style=&quot;margin-top:20px; padding:10px; border:1px solid #ddd;&quot;&amp;gt;
        &amp;lt;p&amp;gt;보낸 시각: &amp;lt;span th:text=&quot;${sendTime}&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1764728916342&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MailDTO {
    private String to;
    private String subject;
    private String title;
    private String message;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1764728834710&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class MailService {

    private final JavaMailSender mailSender;
    private final SpringTemplateEngine templateEngine;

    public void sendTemplateMail(MailDTO dto) throws MessagingException {

        // MIME 메일 객체 생성
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, &quot;UTF-8&quot;);

        // 제목 / 받는사람 설정
        helper.setTo(dto.getTo());
        helper.setSubject(dto.getSubject());

        // 템플릿에 넣을 데이터 구성
        Context context = new Context();
        context.setVariable(&quot;title&quot;, dto.getTitle());
        context.setVariable(&quot;message&quot;, dto.getMessage());
        context.setVariable(&quot;sendTime&quot;, LocalDateTime.now().toString());

        // HTML 템플릿 렌더링
        String html = templateEngine.process(&quot;mail/sample-mail&quot;, context);

        // HTML 메일로 설정
        helper.setText(html, true);

        mailSender.send(mimeMessage);
    }
}&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 data-start=&quot;2699&quot; data-end=&quot;2816&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;templateEngine.process(&quot;mail/sample-mail&quot;, context);&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;rarr; templates/mail/sample-mail.html 파일을 읽어서 HTML을 만들어줌&lt;/span&gt;&lt;/li&gt;
&lt;li data-start=&quot;2817&quot; data-end=&quot;2873&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;helper.setText(html, true)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;rarr; true = HTML이라는 의미&lt;/span&gt;&lt;/li&gt;
&lt;li data-start=&quot;2874&quot; data-end=&quot;2933&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;메일 내용에 variables(title, message, sendTime)을 모두 바인딩할 수 있음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1764728943566&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
@RequiredArgsConstructor
@RequestMapping(&quot;/api/mail&quot;)
public class MailController {

    private final MailService mailService;

    @PostMapping(&quot;/send-template&quot;)
    public String sendTemplate(@RequestBody MailDTO dto) throws MessagingException {
        mailService.sendTemplateMail(dto);
        return &quot;success&quot;;
    }
}&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: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;전송 테스트 (POST)&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1764728974901&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;POST /api/mail/send-template
{
  &quot;to&quot;: &quot;받을사람@gmail.com&quot;,
  &quot;subject&quot;: &quot;템플릿 메일 테스트&quot;,
  &quot;title&quot;: &quot;환영합니다!&quot;,
  &quot;message&quot;: &quot;템플릿 기반 HTML 메일이 정상적으로 발송되었습니다.&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이번 글은 기본 설정과 템플릿 기반 메일 발송까지 정리한 내용이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ️ 백엔드/☕JAVA</category>
      <category>gmail smtp 설정</category>
      <category>gmail 앱비밀번호</category>
      <category>java mail sender</category>
      <category>spring boot email</category>
      <category>spring mail html</category>
      <category>thymeleaf 이메일 템플릿</category>
      <category>메일 인증 구현</category>
      <category>스프링부트 smtp 오류</category>
      <category>스프링부트 비밀번호 재설정</category>
      <category>템플릿 메일 발송</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/201</guid>
      <comments>https://somnote.tistory.com/201#entry201comment</comments>
      <pubDate>Wed, 3 Dec 2025 11:33:34 +0900</pubDate>
    </item>
    <item>
      <title># 인텔리제이(intellij) - 전체파일 단어 일괄 수정하는 방법 (단축키 설정)</title>
      <link>https://somnote.tistory.com/200</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;상단 메뉴에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Edit - Find&amp;nbsp; - Replace in Files...를 선택한 후&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;741&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IyfEx/dJMcafrxr9Z/Rik117mIpyKI61Xz6pBkq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IyfEx/dJMcafrxr9Z/Rik117mIpyKI61Xz6pBkq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IyfEx/dJMcafrxr9Z/Rik117mIpyKI61Xz6pBkq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIyfEx%2FdJMcafrxr9Z%2FRik117mIpyKI61Xz6pBkq0%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;615&quot; height=&quot;741&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;741&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;821&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/orbaK/dJMcafrxr96/OJtfE0nq5FtXAnKom7rNk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/orbaK/dJMcafrxr96/OJtfE0nq5FtXAnKom7rNk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/orbaK/dJMcafrxr96/OJtfE0nq5FtXAnKom7rNk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2ForbaK%2FdJMcafrxr96%2FOJtfE0nq5FtXAnKom7rNk0%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;821&quot; height=&quot;821&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;821&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;다들 컨트롤 쉬프트 R이라는데 아무리 눌러도 안되더라,,, (캡처에는 설정 후 모습)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보니까 단축키 지정이 안되있는데 나처럼 안되어있는 사람들을 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단축키 설명하는 방법도 추가로 적겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;File - Settings에서 keymap 검색&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btNyNz/dJMcafZm7vf/zX0NA8dZbec0sXUidPtxFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btNyNz/dJMcafZm7vf/zX0NA8dZbec0sXUidPtxFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btNyNz/dJMcafZm7vf/zX0NA8dZbec0sXUidPtxFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtNyNz%2FdJMcafZm7vf%2FzX0NA8dZbec0sXUidPtxFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;977&quot; height=&quot;737&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보시면 Main Menu라는 목록이 있는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewDZ0A/dJMcadHc5yq/ad6j7fpRWRk9DR6TJcvksk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewDZ0A/dJMcadHc5yq/ad6j7fpRWRk9DR6TJcvksk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewDZ0A/dJMcadHc5yq/ad6j7fpRWRk9DR6TJcvksk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FewDZ0A%2FdJMcadHc5yq%2Fad6j7fpRWRk9DR6TJcvksk%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;631&quot; height=&quot;335&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Edit - Fine 폴더에 Replace in Files...가 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z3xI7/dJMcagKKppN/rhnIdIXVXSnRksSd4JVWO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z3xI7/dJMcagKKppN/rhnIdIXVXSnRksSd4JVWO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z3xI7/dJMcagKKppN/rhnIdIXVXSnRksSd4JVWO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz3xI7%2FdJMcagKKppN%2FrhnIdIXVXSnRksSd4JVWO1%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;591&quot; height=&quot;408&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;408&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;165&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O4tLC/dJMcaiPhTda/XvCGrvigeWrwsp7hrGP2z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O4tLC/dJMcaiPhTda/XvCGrvigeWrwsp7hrGP2z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O4tLC/dJMcaiPhTda/XvCGrvigeWrwsp7hrGP2z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO4tLC%2FdJMcaiPhTda%2FXvCGrvigeWrwsp7hrGP2z0%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;165&quot; height=&quot;194&quot; data-origin-width=&quot;165&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요런창이 뜰텐데 이걸 누르고 단축키를 지정해주면 됩니다.&lt;/p&gt;</description>
      <category> IDE/intelliJ</category>
      <category>인텔리제이 단축키 변경</category>
      <category>인텔리제이 일괄 바꾸기</category>
      <category>인텔리제이 일괄 변경</category>
      <category>인텔리제이 전체 검색</category>
      <category>인텔리제이 전체 바꾸기</category>
      <category>인텔리제이 전체 수정</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/200</guid>
      <comments>https://somnote.tistory.com/200#entry200comment</comments>
      <pubDate>Tue, 2 Dec 2025 15:29:45 +0900</pubDate>
    </item>
    <item>
      <title># 이벤트 위임(Event Delegation) 완전 이해하기</title>
      <link>https://somnote.tistory.com/199</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;DOM에서 요소를 클릭할 때 실행되는 이벤트는 **자식 &amp;rarr; 부모로 전파(버블링)**됩니다.&lt;br /&gt;이 특성을 이용해서, &amp;ldquo;여러 자식 요소마다 이벤트를 붙이지 않고 부모 하나에 이벤트를 맡기는 방식&amp;rdquo;을 **이벤트 위임(Event Delegation)**이라고 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 기존 방식: 요소마다 이벤트 직접 등록&lt;/h2&gt;
&lt;pre id=&quot;code_1764116619541&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;deleteBtn.addEventListener(&quot;click&quot;, function(){
    newDiv.remove();
})&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-end=&quot;588&quot; data-start=&quot;575&quot; data-ke-size=&quot;size26&quot;&gt;✔ 동작 방식&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;668&quot; data-start=&quot;589&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;625&quot; data-start=&quot;589&quot;&gt;카드 1개 생성 &amp;rarr; 삭제 버튼 1개 &amp;rarr; 이벤트 핸들러 1개&lt;/li&gt;
&lt;li data-end=&quot;668&quot; data-start=&quot;626&quot;&gt;카드 100개 생성 &amp;rarr; 삭제 버튼 100개 &amp;rarr; 이벤트 핸들러 100개&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;695&quot; data-start=&quot;670&quot; data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;요소 개수만큼 이벤트가 증가&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-end=&quot;875&quot; data-start=&quot;864&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;875&quot; data-start=&quot;864&quot; data-ke-size=&quot;size16&quot;&gt;이 방식의 문제점:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;957&quot; data-start=&quot;876&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;905&quot; data-start=&quot;876&quot;&gt;카드 100개면 이벤트 핸들러도 100개 생김&lt;/li&gt;
&lt;li data-end=&quot;926&quot; data-start=&quot;906&quot;&gt;성능 떨어지고 관리가 복잡해짐&lt;/li&gt;
&lt;li data-end=&quot;957&quot; data-start=&quot;927&quot;&gt;동적으로 추가된 요소는 처음엔 이벤트가 안 붙어있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이벤트 위임을 사용하면 더 효율적인 방식으로 변경 할 수 있음&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 이벤트 위임 방식: 부모에 이벤트 한 번만 등록&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제 버튼 클릭 이벤트를 삭제 버튼에 붙이지 않고&lt;br /&gt;&lt;b&gt;부모 요소(cards) 하나에만 이벤트를 등록한다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764116724244&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cards.addEventListener(&quot;click&quot;, function(e){
    if (e.target.classList.contains(&quot;delete-btn&quot;)) {
        e.target.parentElement.remove();
    }
});&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-end=&quot;1072&quot; data-start=&quot;1059&quot; data-ke-size=&quot;size26&quot;&gt;✔ 동작 방식&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1158&quot; data-start=&quot;1073&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1103&quot; data-start=&quot;1073&quot;&gt;클릭된 요소가 .delete-btn인지 체크&lt;/li&gt;
&lt;li data-end=&quot;1120&quot; data-start=&quot;1104&quot;&gt;맞으면 해당 카드 삭제&lt;/li&gt;
&lt;li data-end=&quot;1158&quot; data-start=&quot;1121&quot;&gt;삭제 버튼이 10개든 100개든 &lt;b&gt;이벤트 핸들러는 단 하나&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1170&quot; data-start=&quot;1160&quot; data-ke-size=&quot;size16&quot;&gt;장점:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1234&quot; data-start=&quot;1171&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1189&quot; data-start=&quot;1171&quot;&gt;성능 좋음 (핸들러 1개)&lt;/li&gt;
&lt;li data-end=&quot;1212&quot; data-start=&quot;1190&quot;&gt;동적으로 추가된 요소도 자동 적용&lt;/li&gt;
&lt;li data-end=&quot;1234&quot; data-start=&quot;1213&quot;&gt;코드가 단순해지고 유지보수 편함&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 실제 적용 포인트&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1608&quot; data-start=&quot;1573&quot;&gt;리스트나 테이블처럼 &lt;b&gt;반복되는 요소가 많을 때 필수&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1640&quot; data-start=&quot;1609&quot;&gt;버튼, 메뉴, 아이템 삭제/토글 등에 매우 효과적&lt;/li&gt;
&lt;li data-end=&quot;1672&quot; data-start=&quot;1641&quot;&gt;SPA, 동적 UI에서 거의 기본 패턴으로 사용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 Vue/React 같은 프레임워크가 나오기 전부터&lt;br /&gt;&lt;b&gt;jQuery 시절에도 기본적인 성능 최적화 방식&lt;/b&gt;으로 널리 사용되던 패턴이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리 정리&lt;/h2&gt;
&lt;p data-end=&quot;1910&quot; data-start=&quot;1890&quot; data-ke-size=&quot;size16&quot;&gt;이벤트 위임을 한 문장으로 정리하면:&lt;/p&gt;
&lt;blockquote data-end=&quot;1969&quot; data-start=&quot;1912&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1969&quot; data-start=&quot;1914&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;동적으로 변하는 UI를 효율적으로 제어하기 위해, 이벤트를 부모에게 한 번만 맡기는 방식&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ️ 프론트엔드/ JS, React</category>
      <category>DOM</category>
      <category>DOM조작</category>
      <category>Event Delegation</category>
      <category>Front-End</category>
      <category>javascript</category>
      <category>동적UI</category>
      <category>웹개발</category>
      <category>이벤트버블링</category>
      <category>이벤트위임</category>
      <category>자바스크립트기초</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/199</guid>
      <comments>https://somnote.tistory.com/199#entry199comment</comments>
      <pubDate>Wed, 26 Nov 2025 09:30:00 +0900</pubDate>
    </item>
    <item>
      <title># PostgreSQL pg_dump &amp;middot; pg_restore 사용법 및 로컬 DB 복원 정리</title>
      <link>https://somnote.tistory.com/198</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;DB 사용하다 보면 클라우드나 다른 서버에서 데이터를 백업(덤프)하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이를 로컬 환경으로 복원해야 할 일이 자주 생깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이 글에서는 pg_dump로 백업을 만들고, pg_restore를 이용해 로컬 DB&amp;middot;특정 스키마에 복원하는 전체 과정을 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. pg_dump로 DB 백업(dump) 만들기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;백업(dump) 생성은 PostgreSQL의 pg_dump를 이용합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Custom format(-F c)으로 백업하면 나중에 pg_restore로 스키마 단위 복원이 가능합니다.&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: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;예시 명령&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764052117056&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pg_dump -h {host} -U {user} -d {database} -F c -f &quot;경로\파일명.dump&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;옵션 설명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 139px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;옵션&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-h&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;접속할 서버 주소. Render 등 외부 서버일 경우 외부 호스트, 로컬은 localhost&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-U&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;PostgreSQL 사용자명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-d&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;백업할 DB 이름&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-F c&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Custom format (pg_restore로 복원 가능)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-f&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;출력 파일 경로&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. localhost 확인 (로컬 PostgreSQL 서버 목록 확인)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;로컬 DB에 복원하기 전에, 내 PC에서 어떤 DB가 존재하는지 확인해 보겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이 명령은 **CMD(명령 프롬프트)**에서 실행해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764052211259&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;psql -h localhost -U postgres -l&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;대부분 설치 직후에는 아래 3개가 보입니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;DB 이름&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;postgres&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;기본 DB (우리가 주로 복원하게 되는 DB)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;template0&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;시스템 템플릿 DB&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;template1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;새로운 DB 생성 시 기본 템플릿&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;즉, 로컬에서 우리가 사용할 DB는 대부분 &lt;b&gt;postgres&lt;/b&gt; DB입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3. pg_restore를 이용한 로컬 DB 복원&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;1329&quot; data-start=&quot;1303&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3-1. 특정 스키마(abc)에 복원&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1373&quot; data-start=&quot;1331&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이미 로컬 DB(postgres)에 abc스키마가 존재한다고 가정하면:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764052321418&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pg_restore -h localhost -U postgres -d postgres -n abc &quot;C:\경로\파일.dump&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;옵션 설명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;옵션&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-d postgres&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;로컬의 postgres DB에 복원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;-n split&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;split 스키마에만 복원&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&quot;파일.dump&quot;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;백업본 파일 경로&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-end=&quot;1608&quot; data-start=&quot;1600&quot; data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;주의&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-end=&quot;1671&quot; data-start=&quot;1609&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;dump 안의 원본 스키마가 public이면 abc로 들어가지 않을 수도 있다. 그럴 땐 아래 옵션 사용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764052387026&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pg_restore -h localhost -U postgres -d postgres -N public --schema=abc &quot;C:\경로\파일.dump&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;4. 복원 결과 확인&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;복원 후 아래 명령으로 테이블이 정상적으로 들어왔는지 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;스키마의 테이블 목록 보기&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1764052426794&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;\dt abc.*&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;5. 정리&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2246&quot; data-start=&quot;2216&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;pg_dump &amp;rarr; DB 전체를 백업하는 도구&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2293&quot; data-start=&quot;2247&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;pg_restore &amp;rarr; Custom format dump를 복원하는 도구&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2357&quot; data-start=&quot;2294&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;로컬 복원 시 -h localhost를 사용하면 내 PC에만 복원되므로 다른 서버에 영향을 주지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2405&quot; data-start=&quot;2358&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;dump 생성 시 원본 스키마 구조에 따라 복원할 스키마 옵션이 다를 수 있다&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2468&quot; data-start=&quot;2406&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;pgAdmin의 SQL 창에서는 pg_restore가 동작하지 않음 &amp;rarr; 반드시 CMD에서 실행해야 함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> ️ 백엔드/ ️DB</category>
      <category>DatabaseMigration</category>
      <category>DB덤프파일</category>
      <category>pg_dump</category>
      <category>pg_restore</category>
      <category>PostgreSQL</category>
      <category>PostgreSQL백업</category>
      <category>PostgreSQL복원</category>
      <category>PostgreSQL튜토리얼</category>
      <category>데이터베이스백업</category>
      <category>로컬DB복원</category>
      <author>뭉지맘</author>
      <guid isPermaLink="true">https://somnote.tistory.com/198</guid>
      <comments>https://somnote.tistory.com/198#entry198comment</comments>
      <pubDate>Tue, 25 Nov 2025 15:35:08 +0900</pubDate>
    </item>
  </channel>
</rss>