<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>나의 개발 일상 기록</title>
    <link>https://hsti.tistory.com/</link>
    <description>기억보단 기록으로 지금까지의 경험을 차곡차곡 쌓아가는 블로그입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 6 Aug 2026 02:06:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>느린 거북이</managingEditor>
    <item>
      <title>[Tomcat] JSESSIONID</title>
      <link>https://hsti.tistory.com/95</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JSESSIONID&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Session에 대해서 문득 궁금한 부분이 생겼습니다. 만약 사용자 A와 사용자 B가 있다고 한다면 로그인이 된 상태에서 서버는 Session의 정보에 담긴 각 사용자에 대한 로그인 아이디를 HttpSession.getAttribute(&quot;userId&quot;) 이와 같은 방식으로 정보를 조회를 하는데 과연 어떤 방식을 통해 각 사용자 Session을 구분해서 정보를 가지고 오는 걸까라는 궁금증이 생겼습니다. 구글링을 통해 JSESSIONID를 통해 각 브라우저의 Session을 구분해서 정보를 조회 할 수 있다고 알게되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;JSESSIONID란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tomcat 컨테이너에서 세션을 유지하기 위해 발급하는 키로 HTTP 프로토콜은 무상태(stateless) 하기 때문에 요청 시 마다 새로운 연결이 생성되고 응답 후 연결은 끊어지게 되므로 상태를 유지할 수 없게 됩니다. 상태를 저장하기 위해서 Tomcat은 JSESSIONID 쿠키를 클라이언트에게 발급해주고 이 값을 통해 세션을 유지할 수 있도록 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;쿠키 형태로 전송되는 JSESSIONID 동작방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 사용자가 브라우저를 통해 웹 페이지 URL 입력 후 서버에 요청을 한다면 서버에서 요청한 사용자가 최초 요청했다고 판단되면 JSESSIONID 값을 사용자에게 전달해줍니다. 전달된 JSESSIONID 값은 쿠키 형태로 사용자의 매번 요청때마다 서버에 전달하게 됩니다. 사용자에게 전달 받은 JSESSIONID 값으로 동일한 사용자의 요청인지를 판단하여 사용자 정보를 유지할 수 있게 됩니다.&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>Spring</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/95</guid>
      <comments>https://hsti.tistory.com/95#entry95comment</comments>
      <pubDate>Thu, 24 Mar 2022 07:53:51 +0900</pubDate>
    </item>
    <item>
      <title>JVM Cannot allocate memory 에러 해결</title>
      <link>https://hsti.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Spring boot를 사용해서 어플리케이션을 개발하는 중 jenkins 자동 배포를 하는 과정에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 에러가 나면서 build가 되지 않았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uewIe/btru1bZalbi/VV8OdRUaFuvwwjVaVxPoJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uewIe/btru1bZalbi/VV8OdRUaFuvwwjVaVxPoJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uewIe/btru1bZalbi/VV8OdRUaFuvwwjVaVxPoJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuewIe%2Fbtru1bZalbi%2FVV8OdRUaFuvwwjVaVxPoJ1%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;1016&quot; height=&quot;121&quot; data-origin-width=&quot;1016&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 물리적 RAM 또는 스왑 공간 부족&lt;/li&gt;
&lt;li&gt;프로세스 크기 제한에 도달&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 통해 많은 다양한 해결 방법이 있다는 것을 알게 되었습니다. 그&amp;nbsp; 중에서도 저는 Swap 공간을 늘리는 방법으로 접근하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Swap 파티셔닝&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Swap 공간 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;free -h&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tkgBo/btruYSMxM6y/M9gMQbbcdfH85fbZjy7Ji0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tkgBo/btruYSMxM6y/M9gMQbbcdfH85fbZjy7Ji0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tkgBo/btruYSMxM6y/M9gMQbbcdfH85fbZjy7Ji0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtkgBo%2FbtruYSMxM6y%2FM9gMQbbcdfH85fbZjy7Ji0%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;664&quot; height=&quot;71&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;86&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;size18&quot;&gt;&lt;b&gt;2. Swap 공간 확인&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$ touch /var/spool/swap/swapfile 
$ dd if=/dev/zero of=/var/spool/swap/swapfile count=2048000 bs=1024&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;swap 파일 생성 후 2G의 메모리를 할당하였습니다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;chmod 600 /var/spool/swap/swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 설정을 해줍니다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;$ mkswap /var/spool/swap/swapfile
$ swapon /var/spool/swap/swapfile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 포맷을 Swap으로 변환하고 Swap File로 등록해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Swap 영역 확인&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jvxea/btru1aTr1Me/zUt5B7j0wuSidOE7Sa5Sdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jvxea/btru1aTr1Me/zUt5B7j0wuSidOE7Sa5Sdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jvxea/btru1aTr1Me/zUt5B7j0wuSidOE7Sa5Sdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJvxea%2Fbtru1aTr1Me%2FzUt5B7j0wuSidOE7Sa5Sdk%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;752&quot; height=&quot;74&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;80&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;size18&quot;&gt;&lt;b&gt;4. jenkins 자동 배포&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RMaVm/btru2nZkURK/cjpijUAnsvh49GOSfuksXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RMaVm/btru2nZkURK/cjpijUAnsvh49GOSfuksXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RMaVm/btru2nZkURK/cjpijUAnsvh49GOSfuksXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRMaVm%2Fbtru2nZkURK%2FcjpijUAnsvh49GOSfuksXk%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;839&quot; height=&quot;225&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;해결!!&lt;/p&gt;</description>
      <category>AWS</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/94</guid>
      <comments>https://hsti.tistory.com/94#entry94comment</comments>
      <pubDate>Fri, 4 Mar 2022 00:31:54 +0900</pubDate>
    </item>
    <item>
      <title>[FCM] FireBase를 활용한 Web Push Alarm</title>
      <link>https://hsti.tistory.com/93</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;FireBase를&amp;nbsp;활용한&amp;nbsp;Web&amp;nbsp;Push&amp;nbsp;Alarm&amp;nbsp;&lt;/b&gt;&lt;/h2&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;497&quot; data-origin-height=&quot;167&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9rRvb/btruc57eEs2/k4OdOiE35mKhG7WmhmKJZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9rRvb/btruc57eEs2/k4OdOiE35mKhG7WmhmKJZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9rRvb/btruc57eEs2/k4OdOiE35mKhG7WmhmKJZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9rRvb%2Fbtruc57eEs2%2Fk4OdOiE35mKhG7WmhmKJZ1%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;497&quot; height=&quot;167&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;167&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사전 작업&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Firebase 프로젝트 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://console.firebase.google.com/&quot;&gt;https://console.firebase.google.com/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 url을 접속하여 Friebase 프로젝트를 생성합니다. 프로젝트 생성 과정은 간단하여 생략하였습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CrJR8/btruiTdnQ1C/JaiFDPSkW4HX4fDFFVhBL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CrJR8/btruiTdnQ1C/JaiFDPSkW4HX4fDFFVhBL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CrJR8/btruiTdnQ1C/JaiFDPSkW4HX4fDFFVhBL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCrJR8%2FbtruiTdnQ1C%2FJaiFDPSkW4HX4fDFFVhBL0%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;390&quot; height=&quot;170&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Web 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림에서 Web(&lt;b&gt;3번째 아이콘&lt;/b&gt;)아이콘을 클릭하여 Web을 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QscMU/btruk3s6fzK/Eb5XrynqrsLwET434YPeH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QscMU/btruk3s6fzK/Eb5XrynqrsLwET434YPeH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QscMU/btruk3s6fzK/Eb5XrynqrsLwET434YPeH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQscMU%2Fbtruk3s6fzK%2FEb5XrynqrsLwET434YPeH0%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;294&quot; height=&quot;150&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 웹 닉네임을 본인이 원하는 명으로 기입 후 앱 등록 버큰을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWNCI/btruc7jIvUc/XQtOfSXTNJY3FaFyPEHr20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWNCI/btruc7jIvUc/XQtOfSXTNJY3FaFyPEHr20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWNCI/btruc7jIvUc/XQtOfSXTNJY3FaFyPEHr20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWNCI%2Fbtruc7jIvUc%2FXQtOfSXTNJY3FaFyPEHr20%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;341&quot; height=&quot;232&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;script&amp;gt; 태그 사용을 선택 후 [콘솔로 이동] 버큰을 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;922&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKOFly/btruc4zTIWe/TPhKDUk9s9L5MvIjaakxe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKOFly/btruc4zTIWe/TPhKDUk9s9L5MvIjaakxe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKOFly/btruc4zTIWe/TPhKDUk9s9L5MvIjaakxe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKOFly%2Fbtruc4zTIWe%2FTPhKDUk9s9L5MvIjaakxe0%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;357&quot; height=&quot;345&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;922&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 프로젝트 새 비공개 키 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 진입 후 좌측 상단에 아래의 그림에 표시된 문양을 클릭 후 프로젝트 설정을 클릭합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKNtxr/btruc5ldRjD/ZWkkAxHqgC3xd0XGmgbvNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKNtxr/btruc5ldRjD/ZWkkAxHqgC3xd0XGmgbvNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKNtxr/btruc5ldRjD/ZWkkAxHqgC3xd0XGmgbvNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKNtxr%2Fbtruc5ldRjD%2FZWkkAxHqgC3xd0XGmgbvNK%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;372&quot; height=&quot;174&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;222&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;프로젝트 설정 화면에서 상단의 Tab 메뉴에서 서비스 계정을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;133&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K3EQI/btrufE2mZ18/5SQslTjrNrHqcAaO7DfboK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K3EQI/btrufE2mZ18/5SQslTjrNrHqcAaO7DfboK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K3EQI/btrufE2mZ18/5SQslTjrNrHqcAaO7DfboK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK3EQI%2FbtrufE2mZ18%2F5SQslTjrNrHqcAaO7DfboK%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;302&quot; height=&quot;90&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;133&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 계정 Tab을 선택하면 [새 비공개 키 생성] 버튼을 클릭하하면 ***.json 파일이 생성됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eAc6mh/btrufE89GGA/1SACthlHyVRgyslmAcpJk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eAc6mh/btrufE89GGA/1SACthlHyVRgyslmAcpJk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eAc6mh/btrufE89GGA/1SACthlHyVRgyslmAcpJk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeAc6mh%2FbtrufE89GGA%2F1SACthlHyVRgyslmAcpJk0%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;214&quot; height=&quot;74&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;74&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;size18&quot;&gt;&lt;b&gt;4. Script에 설정할 프로젝트 정보 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 설정 화면에 상단의 Tab 메뉴에서 일반을 선택합니다. 스크롤을 아래로 내리면&amp;nbsp; SDK 설정 및 구성에 대한 정보를 확인할 수 있습니다. 해당 부분은 추후 Script에서 사용할 정보 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;703&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddYJVb/btrujJIriCZ/vzWY7eM7jDp4QtT3FtRqDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddYJVb/btrujJIriCZ/vzWY7eM7jDp4QtT3FtRqDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddYJVb/btrujJIriCZ/vzWY7eM7jDp4QtT3FtRqDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddYJVb%2FbtrujJIriCZ%2FvzWY7eM7jDp4QtT3FtRqDk%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;342&quot; height=&quot;703&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;703&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;FCM 작업&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FCM Web Push를 구현하기 위해 아래의 그림처럼 Java 및 다른 파일들이 필요합니다. 사전 작업 단계에서 '새 비공개 키 생성' 에서 받은 json 파일은 resources 경로 아래에 위치해 둡니다. (java11, gradle 환경에서 진행하였습니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coPNNa/btruqEVqIdS/u1q9Yq38d9t21kiHieTkZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coPNNa/btruqEVqIdS/u1q9Yq38d9t21kiHieTkZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coPNNa/btruqEVqIdS/u1q9Yq38d9t21kiHieTkZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoPNNa%2FbtruqEVqIdS%2Fu1q9Yq38d9t21kiHieTkZ1%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;287&quot; height=&quot;264&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Java 백엔드 작업&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Dependecny 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;build.gradle&lt;/p&gt;
&lt;pre id=&quot;code_1645877326081&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
	// FCM push
	implementation 'com.google.firebase:firebase-admin:6.8.1'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;FCM 초기화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;어플맄이션이 시작될 때 Firebas 프로젝트에 본인의 APP을 등록해주어야 합니다. 만일 두번 등록이 되면 에러가 나므로 시작할 때 초기화를 해줍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FirebaseInt&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1645877450701&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
public class FirebaseInit {

    private static final String path = &quot;fooddelivery-f80a5-firebase-adminsdk-arc1t-21f2efbc96.json&quot;;

    @PostConstruct
    public void init(){
        try{
            FirebaseOptions options = new FirebaseOptions.Builder()
                    .setCredentials(
                            GoogleCredentials.fromStream(
                                    new ClassPathResource(path).getInputStream()
                            )
                    ).build();

            if(FirebaseApp.getApps().isEmpty()){
                FirebaseApp.initializeApp(options);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Send Message&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메세지를 보낼 때 토큰과 토픽 방식으로 보낼 수 있습니다. 해당 Service에서는 Token 방식을 채택하여 메세지를 보내보았습니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FCMService&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1645877734672&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Service
public class FCMService {

    public void sendFcm(FcmNotificationRequest fcmNotificationRequest) {
        Message message = Message.builder()
                .setToken(fcmNotificationRequest.getToken())
                .setWebpushConfig(WebpushConfig.builder().putHeader(&quot;ttl&quot;, &quot;300&quot;)
                        .setNotification(new WebpushNotification(fcmNotificationRequest.getTitle(),
                                fcmNotificationRequest.getMessage()))
                        .build())
                .build();

        try{
            String response = FirebaseMessaging.getInstance().sendAsync(message).get();
            log.info(&quot;Sent message: &quot; + response);
        }catch (Exception e){
            log.error(&quot;FCM PUSH ERROR&quot;);
            log.error(e.getMessage());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Message Builder를 통해 메세지를 정삭적으로 보낸다면 response에는 아래의 그림처럼 message return값을 확인이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;29&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baz95y/btrulSTEtzW/OkGG0xSb3Z2MamZLwTx3L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baz95y/btrulSTEtzW/OkGG0xSb3Z2MamZLwTx3L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baz95y/btrulSTEtzW/OkGG0xSb3Z2MamZLwTx3L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaz95y%2FbtrulSTEtzW%2FOkGG0xSb3Z2MamZLwTx3L1%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;882&quot; height=&quot;29&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;29&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* FCMController는 간단히 request 받았을 경우 html로 보내주는 간단한 로직 구성이 되어있고, MvcConfiguration의 경우 html 경로를 설정해주는 코드가 작성이 되어있기에 생략하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 프론트엔드 작업&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;firebase-messaging-sw.js 파일 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;servicework에 등록하기 위해 firebase-messageing-sw.js 파일을 생성합니다. 해당 파일의 명을 동일하게 해주셔야 servicework에 등록이 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645876997642&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;importScripts('https://www.gstatic.com/firebasejs/5.9.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.9.2/firebase-messaging.js');

// Initialize Firebase
let firebaseConfig = {
    apiKey: &quot;&quot;,
    authDomain: &quot;&quot;,
    projectId: &quot;&quot;,
    storageBucket: &quot;&quot;,
    messagingSenderId: &quot;&quot;,
    appId: &quot;&quot;,
    measurementId: &quot;&quot;
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;firebaseConfig의 내용은 사전 작업 중 &lt;b&gt;4. Script에 설정할 프로젝트 정보 확인&lt;/b&gt;의 내용을 참고하셔서 작성을 하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;fcm.html 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;firebaseConfig에 내용에 들어갈 정보 또한 사전 작업 단계에서 4번 내용을 참고하셔서 작성을 해주시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645878219147&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html xmlns xmlns:th=&quot;http://www.thymeleaf.org&quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
  &amp;lt;title&amp;gt;FCM&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Test page!&amp;lt;/h1&amp;gt;
&amp;lt;script src=&quot;https://www.gstatic.com/firebasejs/5.9.2/firebase.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://www.gstatic.com/firebasejs/5.9.2/firebase-app.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://www.gstatic.com/firebasejs/5.9.2/firebase-messaging.js&quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script th:inline=&quot;javascript&quot;&amp;gt;

    let firebaseConfig = {
        apiKey: &quot;&quot;,
        authDomain: &quot;,
        projectId: &quot;&quot;,
        storageBucket: &quot;&quot;,
        messagingSenderId: &quot;&quot;,
        appId: &quot;&quot;,
        measurementId: &quot;&quot;
    };

    firebase.initializeApp(firebaseConfig);

    const messaging = firebase.messaging();

    messaging.requestPermission()
        .then(function() {

            return messaging.getToken();
        })
        .then(async function(token) {
            console.log(token);

            messaging.onMessage(payload =&amp;gt; {
                console.log(payload);

            })
        })
&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면 초기 진입 시 &lt;span style=&quot;background-color: #e9ecef; color: #212529;&quot;&gt;messaging.requestPermission()&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 에 의해 Push 알람 권한 요청 화면이 나오게 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;권한요청.png&quot; data-origin-width=&quot;1119&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/43zYh/btruxkuEm6b/tlO8S6Ei5kFRgk5l0iWMHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/43zYh/btruxkuEm6b/tlO8S6Ei5kFRgk5l0iWMHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/43zYh/btruxkuEm6b/tlO8S6Ei5kFRgk5l0iWMHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F43zYh%2FbtruxkuEm6b%2FtlO8S6Ei5kFRgk5l0iWMHK%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;475&quot; height=&quot;308&quot; data-filename=&quot;권한요청.png&quot; data-origin-width=&quot;1119&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Token 정보 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 도구를 열어 Console를 확인 해보시면 Token 정보가 나오게 되는 것을 확인하실 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/906IX/btrurTrlZYN/4X8tFFyEz57MmctNxJCPhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/906IX/btrurTrlZYN/4X8tFFyEz57MmctNxJCPhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/906IX/btrurTrlZYN/4X8tFFyEz57MmctNxJCPhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F906IX%2FbtrurTrlZYN%2F4X8tFFyEz57MmctNxJCPhk%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;445&quot; height=&quot;231&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;379&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ServiceWork 등록&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드 작업에서 firebase-messageing-sw.js 파일이 Service Workes에 등록이 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;591&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzYCRE/btrutkBCyZ6/cEZwq9yAefoddLyWCeeW51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzYCRE/btrutkBCyZ6/cEZwq9yAefoddLyWCeeW51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzYCRE/btrutkBCyZ6/cEZwq9yAefoddLyWCeeW51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYCRE%2FbtrutkBCyZ6%2FcEZwq9yAefoddLyWCeeW51%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;707&quot; height=&quot;591&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;591&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Web Push 발송&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;주문 접수 완료 fcm push.png&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvcNY/btruey9NQna/F3KXaoOjb56MJ6gf4Wvlxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvcNY/btruey9NQna/F3KXaoOjb56MJ6gf4Wvlxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvcNY/btruey9NQna/F3KXaoOjb56MJ6gf4Wvlxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqvcNY%2Fbtruey9NQna%2FF3KXaoOjb56MJ6gf4Wvlxk%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;393&quot; height=&quot;142&quot; data-filename=&quot;주문 접수 완료 fcm push.png&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Spring</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/93</guid>
      <comments>https://hsti.tistory.com/93#entry93comment</comments>
      <pubDate>Sat, 26 Feb 2022 21:39:33 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Kafka 설치</title>
      <link>https://hsti.tistory.com/92</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Kafka 설치 과정 정리&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;kafka.png&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lxtJm/btruc6YgQsw/hwAFBRdZKltAlALY309st0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lxtJm/btruc6YgQsw/hwAFBRdZKltAlALY309st0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lxtJm/btruc6YgQsw/hwAFBRdZKltAlALY309st0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlxtJm%2Fbtruc6YgQsw%2FhwAFBRdZKltAlALY309st0%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;522&quot; height=&quot;252&quot; data-filename=&quot;kafka.png&quot; data-origin-width=&quot;522&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Java&amp;nbsp;8&amp;nbsp;버전&amp;nbsp;이상&amp;nbsp;설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo yum install -y java-1.8.0-openjdk-devel.x86_64&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7IWyr/btrubLmcuY9/wygSHEYgUGUBksA5i07Am1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7IWyr/btrubLmcuY9/wygSHEYgUGUBksA5i07Am1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7IWyr/btrubLmcuY9/wygSHEYgUGUBksA5i07Am1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7IWyr%2FbtrubLmcuY9%2FwygSHEYgUGUBksA5i07Am1%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;601&quot; height=&quot;74&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Kafka 설치 및 압축 해제&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; wget https://downloads.apache.org/kafka/3.0.0/kafka_2.12-3.0.0.tgz&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBKAUR/btrueePihdJ/OxxyeuhbTg0Ufa35VWSuKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBKAUR/btrueePihdJ/OxxyeuhbTg0Ufa35VWSuKk/img.png&quot; data-alt=&quot;Kafka 설치&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBKAUR/btrueePihdJ/OxxyeuhbTg0Ufa35VWSuKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBKAUR%2FbtrueePihdJ%2FOxxyeuhbTg0Ufa35VWSuKk%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;671&quot; height=&quot;189&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Kafka 설치&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; tar xvf kafka_2.12-3.0.0.tgz&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgWLFU/btrt6eXdwxP/ReZqFPQN4T6zDskXvrapbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgWLFU/btrt6eXdwxP/ReZqFPQN4T6zDskXvrapbK/img.png&quot; data-alt=&quot;압축 해제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgWLFU/btrt6eXdwxP/ReZqFPQN4T6zDskXvrapbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgWLFU%2Fbtrt6eXdwxP%2FReZqFPQN4T6zDskXvrapbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;123&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;165&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;압축 해제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Kafka&amp;nbsp;heap&amp;nbsp;memory&amp;nbsp;설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; export KAFKA_HEAP_OPTS=&quot;Xmx400m -Xms400m&quot;&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;Kafka 패키지의 기본 힙 메모리 설정이 Kafka = 1G, Zookeeper = 512M 으로 설정되어 있어서 프리티어의 메모리 1G 에서는 Kafka와 Zookeeper를 동시에 실행하면 &quot;Cannot allocate memory&quot;와 같은 문제가 방생합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;19&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYH6Vw/btrt6fhyvot/MQDo4aUEETONXgFrumva90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYH6Vw/btrt6fhyvot/MQDo4aUEETONXgFrumva90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYH6Vw/btrt6fhyvot/MQDo4aUEETONXgFrumva90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYH6Vw%2Fbtrt6fhyvot%2FMQDo4aUEETONXgFrumva90%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;664&quot; height=&quot;19&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;19&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Kafka 설정 파일 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; vi config/server.properties&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;17&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZzLUE/btrt7t1M2mA/5bxkavqnl5ZbcZ1kkqg5qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZzLUE/btrt7t1M2mA/5bxkavqnl5ZbcZ1kkqg5qK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZzLUE/btrt7t1M2mA/5bxkavqnl5ZbcZ1kkqg5qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZzLUE%2Fbtrt7t1M2mA%2F5bxkavqnl5ZbcZ1kkqg5qK%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;544&quot; height=&quot;17&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;17&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림 처럼 두가지 항목을 수정해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LmGcA/btrt41X9wKs/kOZWzgjcnEzaVQPByJnpb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LmGcA/btrt41X9wKs/kOZWzgjcnEzaVQPByJnpb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LmGcA/btrt41X9wKs/kOZWzgjcnEzaVQPByJnpb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLmGcA%2Fbtrt41X9wKs%2FkOZWzgjcnEzaVQPByJnpb1%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;701&quot; height=&quot;104&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;advertised.listeners는 통신을 위해 열어두는 PROTOCOL, IP, PORT를 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. zookeeper 실행 및 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; bin/zookeeper-server-start.sh -daemon config/zookeeper.properties&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; jps&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7.png&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xVZGY/btrt6ewhApj/lk5fWQVzlsUPwdMgDb7DkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xVZGY/btrt6ewhApj/lk5fWQVzlsUPwdMgDb7DkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xVZGY/btrt6ewhApj/lk5fWQVzlsUPwdMgDb7DkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxVZGY%2Fbtrt6ewhApj%2Flk5fWQVzlsUPwdMgDb7DkK%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;854&quot; height=&quot;78&quot; data-filename=&quot;7.png&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. Kafka 실행 및 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; bin/kafka-server-start.sh -daemon config/server.properties&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; jps&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8.png&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezZwzK/btrua5lwCIb/QBHi82GMPmmrEtYFcqrPQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezZwzK/btrua5lwCIb/QBHi82GMPmmrEtYFcqrPQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezZwzK/btrua5lwCIb/QBHi82GMPmmrEtYFcqrPQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezZwzK%2Fbtrua5lwCIb%2FQBHi82GMPmmrEtYFcqrPQk%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;804&quot; height=&quot;96&quot; data-filename=&quot;8.png&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AWS</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/92</guid>
      <comments>https://hsti.tistory.com/92#entry92comment</comments>
      <pubDate>Thu, 24 Feb 2022 14:25:39 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] Redis 설치</title>
      <link>https://hsti.tistory.com/91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Redis 설치 과정 정리&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;redis.png&quot; data-origin-width=&quot;1544&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cklf1X/btruahyJEaH/PbeMN7I4AB0NcAlXLwxBa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cklf1X/btruahyJEaH/PbeMN7I4AB0NcAlXLwxBa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cklf1X/btruahyJEaH/PbeMN7I4AB0NcAlXLwxBa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcklf1X%2FbtruahyJEaH%2FPbeMN7I4AB0NcAlXLwxBa1%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;1544&quot; height=&quot;500&quot; data-filename=&quot;redis.png&quot; data-origin-width=&quot;1544&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Redis 설치 전 linux update를 하고 gcc make 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. linux update&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;yum&amp;nbsp;update&amp;nbsp;-y&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doxeAf/btrt4sVCAr1/bDhcZkMA1i5Ulv12ujVvD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doxeAf/btrt4sVCAr1/bDhcZkMA1i5Ulv12ujVvD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doxeAf/btrt4sVCAr1/bDhcZkMA1i5Ulv12ujVvD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoxeAf%2Fbtrt4sVCAr1%2FbDhcZkMA1i5Ulv12ujVvD1%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;512&quot; height=&quot;95&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;116&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;2. gcc make&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;yum&amp;nbsp;install&amp;nbsp;gcc&amp;nbsp;make&amp;nbsp;-y&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxIxYd/btrt3PXNfj9/2X0kRzYp5lBKDCsvZkePKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxIxYd/btrt3PXNfj9/2X0kRzYp5lBKDCsvZkePKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxIxYd/btrt3PXNfj9/2X0kRzYp5lBKDCsvZkePKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxIxYd%2Fbtrt3PXNfj9%2F2X0kRzYp5lBKDCsvZkePKK%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;612&quot; height=&quot;116&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;147&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;size18&quot;&gt;&lt;b&gt;2. Redis&amp;nbsp;설치&amp;nbsp;및&amp;nbsp;압축풀고&amp;nbsp;gcc&amp;nbsp;make로&amp;nbsp;컴파일&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Redis 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; wget&amp;nbsp;http://download.redis.io/releases/redis-6.2.5.tar.gz&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3png.png&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxR9vN/btrt0Nlzv8F/rLfPKnanjqyloueKm1wLdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxR9vN/btrt0Nlzv8F/rLfPKnanjqyloueKm1wLdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxR9vN/btrt0Nlzv8F/rLfPKnanjqyloueKm1wLdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxR9vN%2Fbtrt0Nlzv8F%2FrLfPKnanjqyloueKm1wLdk%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;515&quot; height=&quot;106&quot; data-filename=&quot;3png.png&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;152&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;2. Redis 압축해제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; tar&amp;nbsp;xzf&amp;nbsp;redis-6.2.5.tar.gz&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bU04hI/btrt5xCL46m/Z6LT7u7j10bKI8hC772371/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bU04hI/btrt5xCL46m/Z6LT7u7j10bKI8hC772371/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bU04hI/btrt5xCL46m/Z6LT7u7j10bKI8hC772371/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbU04hI%2Fbtrt5xCL46m%2FZ6LT7u7j10bKI8hC772371%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;65&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;507&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 경로 진입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; cd&amp;nbsp;redis-6.2.5&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. gcc make 컴파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; make&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sPBlF/btrubMrs6f3/fx7Xk7gEDO6rNzob70d5H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sPBlF/btrubMrs6f3/fx7Xk7gEDO6rNzob70d5H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sPBlF/btrubMrs6f3/fx7Xk7gEDO6rNzob70d5H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsPBlF%2FbtrubMrs6f3%2Ffx7Xk7gEDO6rNzob70d5H1%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;387&quot; height=&quot;66&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 디렉토리&amp;nbsp;생성&amp;nbsp;및&amp;nbsp;Redis&amp;nbsp;설정&amp;nbsp;파일&amp;nbsp;복사&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 디렉토리 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;mkdir&amp;nbsp;/etc/redis&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;mkdir&amp;nbsp;/var/lib/redis&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Redis 설정 파일 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;cp&amp;nbsp;src/redis-server&amp;nbsp;src/redis-cli&amp;nbsp;/usr/local/bin/&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;cp&amp;nbsp;redis.conf&amp;nbsp;/etc/redis/&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MLLIt/btrt4JwJaZz/FzKwXN55fe9VehUY2aMr51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MLLIt/btrt4JwJaZz/FzKwXN55fe9VehUY2aMr51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MLLIt/btrt4JwJaZz/FzKwXN55fe9VehUY2aMr51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMLLIt%2Fbtrt4JwJaZz%2FFzKwXN55fe9VehUY2aMr51%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;596&quot; height=&quot;51&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;65&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. &amp;nbsp;redis.conf&amp;nbsp;설정파일&amp;nbsp;수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 설정파일 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;vi&amp;nbsp;/etc/redis/redis.conf&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kM3qF/btrt7qJvl3c/RZNva3woPUloWmHarYszm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kM3qF/btrt7qJvl3c/RZNva3woPUloWmHarYszm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kM3qF/btrt7qJvl3c/RZNva3woPUloWmHarYszm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkM3qF%2Fbtrt7qJvl3c%2FRZNva3woPUloWmHarYszm1%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;421&quot; height=&quot;49&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7-2.png&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgQPd7/btrt83A1hhp/cGz1tEbKqmnazkzz98bXe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgQPd7/btrt83A1hhp/cGz1tEbKqmnazkzz98bXe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgQPd7/btrt83A1hhp/cGz1tEbKqmnazkzz98bXe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgQPd7%2Fbtrt83A1hhp%2FcGz1tEbKqmnazkzz98bXe1%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;433&quot; height=&quot;44&quot; data-filename=&quot;7-2.png&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;65&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;561&quot; data-origin-height=&quot;49&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F1nDE/btruNWHzKXn/nHJpIDFpkoernSYkZ7PQC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F1nDE/btruNWHzKXn/nHJpIDFpkoernSYkZ7PQC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F1nDE/btruNWHzKXn/nHJpIDFpkoernSYkZ7PQC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF1nDE%2FbtruNWHzKXn%2FnHJpIDFpkoernSYkZ7PQC1%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;413&quot; height=&quot;36&quot; data-origin-width=&quot;561&quot; data-origin-height=&quot;49&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7-4.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bduE8h/btrt3PXOazk/OJWHn1Dch5pHakB0v0wkG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bduE8h/btrt3PXOazk/OJWHn1Dch5pHakB0v0wkG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bduE8h/btrt3PXOazk/OJWHn1Dch5pHakB0v0wkG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbduE8h%2Fbtrt3PXOazk%2FOJWHn1Dch5pHakB0v0wkG0%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;475&quot; height=&quot;51&quot; data-filename=&quot;7-4.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;72&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;size18&quot;&gt;&lt;b&gt;5.&amp;nbsp;Redis&amp;nbsp;서버&amp;nbsp;초기화&amp;nbsp;스크립트&amp;nbsp;다운로드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 스크립트 다운로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; wget&amp;nbsp;https://raw.github.com/saxenap/install-redis-amazon-linux-centos/master/redis-server&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8.png&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rz6Im/btrubKUKXe0/ADols4y29qwbJ6GVY8Bok1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rz6Im/btrubKUKXe0/ADols4y29qwbJ6GVY8Bok1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rz6Im/btrubKUKXe0/ADols4y29qwbJ6GVY8Bok1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frz6Im%2FbtrubKUKXe0%2FADols4y29qwbJ6GVY8Bok1%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;1018&quot; height=&quot;62&quot; data-filename=&quot;8.png&quot; data-origin-width=&quot;1018&quot; data-origin-height=&quot;62&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;size18&quot;&gt;&lt;b&gt;6. /etc/init.d로&amp;nbsp;옮기고&amp;nbsp;권한을&amp;nbsp;설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. init.d 경로 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;mv&amp;nbsp;redis-server&amp;nbsp;/etc/init.d&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 권한 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;chmod&amp;nbsp;755&amp;nbsp;/etc/init.d/redis-server&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9.png&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFwGsE/btrt823afS6/kMwWux1cGcxjkY9JlKcr2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFwGsE/btrt823afS6/kMwWux1cGcxjkY9JlKcr2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFwGsE/btrt823afS6/kMwWux1cGcxjkY9JlKcr2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFwGsE%2Fbtrt823afS6%2FkMwWux1cGcxjkY9JlKcr2k%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;585&quot; height=&quot;35&quot; data-filename=&quot;9.png&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;39&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;size18&quot;&gt;&lt;b&gt;7. redis-server&amp;nbsp;파일에&amp;nbsp;redis&amp;nbsp;항목&amp;nbsp;체크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Redis 항목 체크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;vim&amp;nbsp;/etc/init.d/redis-server&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10.png&quot; data-origin-width=&quot;567&quot; data-origin-height=&quot;17&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccO3aZ/btrt7tNtnJ0/yDDdt9IUAeGTPkkIH8aKh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccO3aZ/btrt7tNtnJ0/yDDdt9IUAeGTPkkIH8aKh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccO3aZ/btrt7tNtnJ0/yDDdt9IUAeGTPkkIH8aKh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccO3aZ%2Fbtrt7tNtnJ0%2FyDDdt9IUAeGTPkkIH8aKh1%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;567&quot; height=&quot;17&quot; data-filename=&quot;10.png&quot; data-origin-width=&quot;567&quot; data-origin-height=&quot;17&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-1.png&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwNBe/btrt7ur7JMH/PrVeufA2BQxAhYq6ug0nD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwNBe/btrt7ur7JMH/PrVeufA2BQxAhYq6ug0nD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwNBe/btrt7ur7JMH/PrVeufA2BQxAhYq6ug0nD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwNBe%2Fbtrt7ur7JMH%2FPrVeufA2BQxAhYq6ug0nD0%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;305&quot; height=&quot;42&quot; data-filename=&quot;10-1.png&quot; data-origin-width=&quot;305&quot; data-origin-height=&quot;42&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8. Redis 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; sudo&amp;nbsp;service&amp;nbsp;redis-server&amp;nbsp;start&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;12.png&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSJc1S/btrt43nHpZI/2IV0rpLBszlv8KkAlAcPnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSJc1S/btrt43nHpZI/2IV0rpLBszlv8KkAlAcPnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSJc1S/btrt43nHpZI/2IV0rpLBszlv8KkAlAcPnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSJc1S%2Fbtrt43nHpZI%2F2IV0rpLBszlv8KkAlAcPnK%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;547&quot; height=&quot;48&quot; data-filename=&quot;12.png&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;48&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;size18&quot;&gt;&lt;b&gt;9. Redis 접속&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;13.png&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pH1zw/btruc6DgNYK/WpfvVzPxk8NuP8bY4yUeuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pH1zw/btruc6DgNYK/WpfvVzPxk8NuP8bY4yUeuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pH1zw/btruc6DgNYK/WpfvVzPxk8NuP8bY4yUeuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpH1zw%2Fbtruc6DgNYK%2FWpfvVzPxk8NuP8bY4yUeuk%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;357&quot; height=&quot;53&quot; data-filename=&quot;13.png&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AWS</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/91</guid>
      <comments>https://hsti.tistory.com/91#entry91comment</comments>
      <pubDate>Wed, 23 Feb 2022 17:39:26 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] TDD(Test-Driven-Development)</title>
      <link>https://hsti.tistory.com/90</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;TDD.png&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNLOFM/btrt4JBMHpx/kkDqC9UD0GYFG4L2emdwsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNLOFM/btrt4JBMHpx/kkDqC9UD0GYFG4L2emdwsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNLOFM/btrt4JBMHpx/kkDqC9UD0GYFG4L2emdwsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNLOFM%2Fbtrt4JBMHpx%2FkkDqC9UD0GYFG4L2emdwsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;386&quot; height=&quot;268&quot; data-filename=&quot;TDD.png&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TDD(Test-Driven-Development)란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD란 '테스트 주도 개발' 이라고 불립니다. 반복 테스트를 이용한 소프트웨어 방법론으로 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현합니다. 짧은 개발 주기의 반복에 의존하는 개발 프로세스입니다. 애자일 방법론 중 하나인 eXtream Programming(XP)의 &amp;lsquo;Test-First&amp;rsquo; 개념에 기반을 둔 단순한 설계를 중요시합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;eXtream Programming(XP)란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;미래에 대한 예측을 최대한 하지 않고 지속적으로 프로토타입을 완성하는 애자일 기방법론 중 하나입니다. 이 방법론은 추가 요구사항이 생기더라도 실시간으로 반영할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TDD 개발주기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨 위의 그림(TDD의 개발주기)를 참고하시면 됩니다.&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;- Red단계 : 실패하는 테스트 코드를 먼저 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Green단계 : 테스트 코드를 성공시키기 위한 실제 코드를 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Yellow단계 : 중복 코드 제거, 일발화 등의 리팩토링을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패하는 테스트 코드를 작성할 때까지 실제 코드를 작성하지 않는 것과, 실패 코드를 작성하지 않는 것과, 실패하는 테스트를 통과할 정도의 최소 실제 코드를 작성해야하는 것이 중요합니다. 이를 통해, 실제 코드에 대해 기대되는 바를 보다 명확하게 정의함으로써 불필요한 설계를 피할 수 있고, 정확한 요구 사항에 집중할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TDD 개발 방식의 장점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보다 튼튼한 객체 지향적인 코드 생산&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD는 코드의 재사용 보장을 명시하므로 TDD를 통한 소프트웨어 개발 시 기능 별 철저한 모듈화가 이뤄집니다. 이는 종속성과 의존성이 낮은 모듈로 조합된 소프트웨어 개발을 가능하게 하며 필요에 따라 모듈을 추가하거나 제거해도 소프트웨어 전체 구조에 영향을 미치지 않게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;재설계 시간의 단축&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드를 먼저 작성하기 때문에 개발자가 지금 무엇을 해야하는지 분명히 정의하고 개발을 시작하게 됩니다. 또한 테스트 시나리오를 작성하면서 다양한 예외사항에 대해 생각해 볼 수 있습니다. 이는 개발 진행 중 소프트웨어의 전반적인 설계가 변경되는 일을 방지할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디버깅 시간의 단축&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD의 경우 자동화 된 유닛테스팅을 전재하므로 특정 버그를 손 쉽게 찾아낼 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트 문서의 대체 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD를 하게 될 경우 테스팅을 자동화 시킴과 동시에 보다 정확한 테스트 근거를 산출할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추가 구현의 용이함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD의 경우 자동화된 유닛 테스팅을 전제하므로 테스트 기간을 획기적으로 단축시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TDD 개발 방식의 단점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 단점은 바로 생산성 저하입니다. 왜냐하면 처음부터 2개의 코드를 짜야하고, 중간 테스트를 하면서 고쳐나가야 하기 때문입니다. TDD방식의 개발 시간은 일반적인 개발 방식에 비해 대략10~30% 정도가 늘어납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/90</guid>
      <comments>https://hsti.tistory.com/90#entry90comment</comments>
      <pubDate>Tue, 22 Feb 2022 17:41:16 +0900</pubDate>
    </item>
    <item>
      <title>[MySQL] Connection Blocked Error</title>
      <link>https://hsti.tistory.com/89</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Connection Blocked Error 현상&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL 서버를 평시 잘 사용을 하다 Connection을 하려고 하는데 갑작스럽게 아래와 같은 에러가 발생하였습니다.&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;ERROR 1129(00000): Host '*' is blocked because of many connection errors. Unblock&amp;nbsp;with&amp;nbsp;'mysqladmin&amp;nbsp;flush-hosts'&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 통해 원인을 파악을 해보니 Host로부터 접속 요청 max_connect_errors 와 관련된 접속 연결 설정값 보다 초과하여 발생하여 설정된 값 이상의 Host에서 연결이 발생하여 MySQL에서는 해당 Host를 Block을 하게 된다는 것을 알게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. MySQL 접속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- mysql -u root -p&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. max_connect_errors&amp;nbsp;카운트&amp;nbsp;확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- select @@global.max_connect_errors;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 에러&amp;nbsp;카운트&amp;nbsp;초기화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- flush&amp;nbsp;hosts;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. max_connections&amp;nbsp;변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- set&amp;nbsp;global&amp;nbsp;max_connections=300;&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;5. max_connect_errors&amp;nbsp;변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- set&amp;nbsp;global&amp;nbsp;max_connect_errors=10000;&lt;/p&gt;</description>
      <category>SQL</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/89</guid>
      <comments>https://hsti.tistory.com/89#entry89comment</comments>
      <pubDate>Tue, 15 Feb 2022 15:58:08 +0900</pubDate>
    </item>
    <item>
      <title>[트래픽 분산처리] 로드밸런싱(Load Balancing)</title>
      <link>https://hsti.tistory.com/88</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;LOAD BALANCING&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 로드밸런싱이란?&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트래픽이 많을 때 여러 대의 서버가 분산처리하여 서버의 로드율을 증가, 부하량, 속도저하 등 고려하여 분산처리하여 해결해주는 서비스입니다.&lt;/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;로드밸런싱(Load Balancing)을 해주는 소프트웨어 혹은 하드웨어 장비를 로드밸런서(Load Balancer)라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 네트워크 상단에 L4 스위치 가상서버가 존재하여 서버로 들어오는 패킷을 리얼 서버로 균일하게 트래픽을 분산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서버에 장애가 발생하면 이를 감지하여 정상적으로 작동하는 서버로 트래픽을 분산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. L4 Load Balancing&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L4는 L4 계층에서 동작하는 Load Balancer 이므로 네트워크 계층이나 트랜스포트 계층의 정보를 바탕으로 로드를 분산합니다. 다시 말해,, IP 주소나 Port번호, MAC 주소, 전송 프로토콜 등에 따라 트래픽을 나누고 분산처리 하는 것이 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;L4.png&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HfY0W/btrtpP3Tg1g/gRhNTqg5iogjM7N0vz0Nj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HfY0W/btrtpP3Tg1g/gRhNTqg5iogjM7N0vz0Nj1/img.png&quot; data-alt=&quot;L4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HfY0W/btrtpP3Tg1g/gRhNTqg5iogjM7N0vz0Nj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHfY0W%2FbtrtpP3Tg1g%2FgRhNTqg5iogjM7N0vz0Nj1%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;451&quot; height=&quot;218&quot; data-filename=&quot;L4.png&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;L4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;L4 Load Balancing 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.&lt;/b&gt; &lt;b&gt;Round Robin&lt;/b&gt;(라운드 로빈 기반)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 세션을 각 서버에 순차적으로 맺어주는 방식입니다. 단순히 순서에 따라 세션을 할당하기 때문에 경우에 따라 같은 처리량을 보장받지는 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 가중치 및 비율 할당 방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서버마다 비율을 설정해두고 해당 비율 만큼 세션을 맺어주는 방식입니다. 특정 서버의 성능이 월등히 뛰어나다면 해당 서버로 세션을 많이 맺어주도록 가중치를 설정하고 나머지 low급의 서버들은 적은 세션이 맺어질 수 있도록 가중치를 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.&lt;/b&gt; &lt;b&gt;Least Connection&lt;/b&gt;(최소 연결 기반)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 가장 적은 세션을 가진 서버로 트래픽을 보내는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. Response Time&lt;/b&gt;(응답 시간 기반)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 가장 빠른 응답 시간을 보내는 서버로 트래픽을 우선 보내주는 방식입니다. 각 서버들의 가용 가능한 리소스와 성능, 처리중인 데이터 양이 다를 경우 적합한 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5.&lt;/b&gt; &lt;b&gt;Hash&lt;/b&gt;(해시 기반)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 특정 클라이언트는 특정 서버로만 할당 시키는 방식입니다. 특정 IP 주소 또는 Port의 클라이언트들은 특정 서버로만 세션이 맺어지도록 합니다. 경로가 보장되며 접속자 수가 많을수록 분산 및 효율이 뛰어납니다.&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;6.&lt;/b&gt; &lt;b&gt;Bandwidth&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. L7 Load Balancing&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L7 Load Balancer는 L4 Load Balancer의 기능을 포함하는 것 뿐만 아니라 OSI 7계층의 프로토콜을 바탕으로도 분산 처리가 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;L7.png&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;303&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rIpNk/btrtifwvcI8/KaKzadkK61kNBfOLADKQPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rIpNk/btrtifwvcI8/KaKzadkK61kNBfOLADKQPK/img.png&quot; data-alt=&quot;L7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rIpNk/btrtifwvcI8/KaKzadkK61kNBfOLADKQPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrIpNk%2FbtrtifwvcI8%2FKaKzadkK61kNBfOLADKQPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;459&quot; height=&quot;234&quot; data-filename=&quot;L7.png&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;303&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;L7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;L7 Load Balancing 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. URL Switching&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 특정 하위 URL들은 특정 서버로 처리하는 방식입니다. 특정 URL을 가진 주소들은 서버가 아닌 별도의 스토리지에 있는 객체 데이터로 바로 연결되도록 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Context Switching&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라이언트가 요청한 특정 리소스에 대해 특정 서버 등으로 연결 해줄 수 있습니다. 예를 들어 이미지 파일에 대해서는 확장자를 참조하여 별도로 구성된 이미지 파일이 있는 서버/스토리지로 직접 연결해줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Persistenve with Cookies&lt;/b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 로드밸런싱 장/단점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로드밸런싱을 이용하면 한 서버가 다운되더라도 이중화시킨 다른 서버에서 서비스를 지속하여, 사용자들이 문제를 인지하지 못하게 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 단지 노드를 추가하는 것 만으로 서비스가 확장성을 가질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로드밸랜서를 사용할 때 어려운 문제 중 하나는 세션 데이터를 관리하는 것입니다. 이러한 문제를 해결하기 위해 세션을 고정(session sticky)를 합니다. 그러나 고정된 세션의 노드에 장애가 발생하면 고정한 의미가 없어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WEB</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/88</guid>
      <comments>https://hsti.tistory.com/88#entry88comment</comments>
      <pubDate>Tue, 15 Feb 2022 15:01:53 +0900</pubDate>
    </item>
    <item>
      <title>[Kafka] Kafka Producer&amp;amp;Consumer Application</title>
      <link>https://hsti.tistory.com/87</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;206&quot; height=&quot;206&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;370&quot; data-filename=&quot;img.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcrZHx/btrgMsNRlTF/4lEg6s29YgwmMkK0hEJJq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcrZHx/btrgMsNRlTF/4lEg6s29YgwmMkK0hEJJq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcrZHx/btrgMsNRlTF/4lEg6s29YgwmMkK0hEJJq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcrZHx%2FbtrgMsNRlTF%2F4lEg6s29YgwmMkK0hEJJq1%2Fimg.png&quot; width=&quot;206&quot; height=&quot;206&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;370&quot; data-filename=&quot;img.png&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kafka Producer Application&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafak Producer는 데이터를 프로듀싱 즉 생산하는 역할을 합니다. 즉, 데이터를 Kafka Topic에 생성합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Producer의 역할&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Topic에 해당하는 메시지를 생성&lt;/li&gt;
&lt;li&gt;특정 Topic으로 데이터를 publish&lt;/li&gt;
&lt;li&gt;처리 실패/재시도&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;&lt;b&gt;gradle 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633073716178&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.3.0'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Kafka Producer를 작성한 코드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633074183815&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Producer{
    public static void main(String[] args) throws IOException{
        
        Properties configs = new Properties();
        configs.put(&quot;bootstrap.servers&quot;, &quot;localhost:9092&quot;);
        configs.put(&quot;key.serializer&quot;, &quot;org.apache.kafka.common.serialization.StringSerializer&quot;);
        configs.put(&quot;value.serializer&quot;, &quot;org.apache.kafka.common.serialization.StringSerializer&quot;);
        
        KafkaProducer &amp;lt;String, String&amp;gt; producer = new KafkaProducer&amp;lt;String, String&amp;gt;(configs);
        
        ProducerRecord record = new ProducerRecord&amp;lt;String, String&amp;gt;(&quot;click_log&quot;, &quot;click&quot;);
        
        producer.send(record);
        
        producer.close();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Properties configs &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Producer를 위한 설정입니다. 자바 프로퍼티 객체를 통해 Producer의 설정을 정의합니다. 부트스트랩 서버 설정을 로컬 호스의 Kafka를 바라보도록 설정을 의미합니다. Kafka broker의 주소목록은 되도록이면 2개 이상의 ip와 port를 설정하도록 권장합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KafkaProducer&amp;nbsp;&amp;lt;String,&amp;nbsp;String&amp;gt;&amp;nbsp;producer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정한 프로퍼티로 Kafka Producer 인스턴스를 생성합니다.&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;ProducerRecord&amp;nbsp;record&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ProducerRecord 인스턴스를 생성할 때 어느 Topic에 넣을 것인지 어떤 key와 value를 담을 것인지 선언할 수 있습니다. 파라미터 개수에 다라 자동으로 오버로딩되어 인스턴스가 생성되므로 이점을 유의하여 ProducerRecord를 생성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1633074772584&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// key값 포함
ProducerRecord record = new ProducerRecord&amp;lt;String, String&amp;gt;(&quot;click_log&quot;, &quot;1&quot;, &quot;click&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;b&gt;producer.send()&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;send() 메서드의 파라미터로 ProducerRecord를 넣으면 전송이 이루어집니다. click_log Topic에 click value가 들어가게 됩니다.&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;producer.close()&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Producer 종료&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kafka Consumer Application&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka에서 Consumer가 데이터를 가져가더라도 데이터가 사라지지 않습니다. 이와 같은 특징은 Kafka 그리고 Kafka Consumer를 데이터 파이프라인으로 운영하는데 매우 핵심적인 역할을 합니다.&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;Kafka Consumer는 기본적으로 Topic의 데이터를 가져옵니다. 데이터는 Topic 내부의 Partition에 저장됩니다. Consumer는 Partition에 저장된 데이터를 가져옵니다. 이렇게 데이터를 가져오는 것을 폴링(polling)이라고 합니다.&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;Consumer의 역할&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Topic의 Partition으로 부터 데이터 Polling&lt;/li&gt;
&lt;li&gt;Partition offset 위치 기록(commit)&lt;/li&gt;
&lt;li&gt;Consumer group을 통해 병렬 처리&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;&lt;b&gt;gradle 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633076239561&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.3.0'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Kafka &lt;b&gt;Consumer&lt;/b&gt;를 작성한 코드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1633076388651&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Consumer{
    public static void main(String[] args){
        Properties configs = new Properties();
        configs.put(&quot;bootstrap.servers&quot;, &quot;localhost:9092&quot;);
        configs.put(&quot;group.id&quot;, &quot;click_log_group&quot;);
        configs.put(&quot;key.serializer&quot;, &quot;org.apache.kafka.common.serialization.StringSerializer&quot;);
        configs.put(&quot;value.serializer&quot;, &quot;org.apache.kafka.common.serialization.StringSerializer&quot;);
        
        KafkaConsumer&amp;lt;String, String&amp;gt; consumer = new KafkaConsumer&amp;lt;String, String&amp;gt;(configs);
        
        consumer.subscribe(Arrays.asList(&quot;click_log&quot;));
        
        while(true){
            ConsumerRecords&amp;lt;String, String&amp;gt; records = consumer.poll(500);
            for(ConsumerRecord&amp;lt;String, String&amp;gt; record : records){
                System.out.pritln(record.value());
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Properties&amp;nbsp;configs&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 Consumer 옵션을 지정할 수 있습니다. bootstrap servers 옵션을 통해 Kafka broker를 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그룹 아이디를 지정합니다. 그룹 아이디는 Consumer&amp;nbsp;그룹이라고도 불립니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KafkaConsumer&amp;lt;String,&amp;nbsp;String&amp;gt;&amp;nbsp;consumer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka Consumer 클래스를 통해 이전에 선언한 설정들을 매개변수로해서 Consumer인스턴스를 생성합니다. 이 Consumer 인스턴스를 통해 데이터를 읽고 처리할 수 있습니다.&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;consumer.subscribe()&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 Topic을 대상으로 데이터를 가져올지 선언합니다.&amp;nbsp;만약 특정 토픽의 전체 Partition이 아니라 일부 Partition의 데이터만 가져오고 싶다면 아래의 코드처럼 assign() 메서드를 사용하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1633076902292&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;TopicPartition partition0 = new TopicPartition(topicName, 0);
TopicPartition partition1 = new TopicPartition(topicName, 1);
consumer.assign(Arrays.asList(partition0, partition1));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;while(true)폴링 루프 구문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka Consumer에서 폴링 루프는 poll()메서드가 포함된 무한루프를 말합니다. Consumer API의 핵심은 broker로부터 연속적으로 그리고 Consumer가 허락하는 한 많은 데이터를 읽는 것입니다. 이런 측면에서 폴링 루프는 Consumer API의 핵심 로직이라고 볼 수 있습니다. Consumer는 poll() 메서드를 통해 데이터를 가져오는데 poll()메서드에서 설정한 시간동안 데이터를 기다리게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/87</guid>
      <comments>https://hsti.tistory.com/87#entry87comment</comments>
      <pubDate>Tue, 5 Oct 2021 09:27:47 +0900</pubDate>
    </item>
    <item>
      <title>[Kafka] Kafka란?</title>
      <link>https://hsti.tistory.com/86</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kafka&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;370&quot; data-filename=&quot;img.png&quot; width=&quot;206&quot; height=&quot;206&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FXXxA/btrgzJuYIbi/KMECyuuGLaUQFkMyHLPvXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FXXxA/btrgzJuYIbi/KMECyuuGLaUQFkMyHLPvXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FXXxA/btrgzJuYIbi/KMECyuuGLaUQFkMyHLPvXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFXXxA%2FbtrgzJuYIbi%2FKMECyuuGLaUQFkMyHLPvXk%2Fimg.png&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;370&quot; data-filename=&quot;img.png&quot; width=&quot;206&quot; height=&quot;206&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위키백과에서 Kafak는 실시간 데이터 피드를 관리하기 위해 통일된, 높은 처리량, 낮은 지연시간을 지닌 플랫폼을 제공하는 것이 목표이며 분산 트랜잭션 로그로 구성된 상당히 확장 가능한 pub/sub 메시지 큐로 정의한다고 나와있습니다.&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;데이터 전송하는 Source 애플리케이션과 데이터를 받는 Target 애플리케이션이 있었습니다. Source &amp;amp; Target 애플리케이션들이 많아지면서 데이터를 전송하는 라인이 매우 복잡해졌습니다. 데이터 전송 라인이 많아지면 배포와 장애에 대응하기가 힘들어지니다. 그래서 Apache Kafka는 이러한 복잡함을 해결하기 위해 개발되었습니다.&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-origin-width=&quot;963&quot; data-origin-height=&quot;371&quot; data-filename=&quot;제목 없음.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dRhfs8/btrgwCJnW21/KQ3CppdHkiG3TkyUnkQHVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dRhfs8/btrgwCJnW21/KQ3CppdHkiG3TkyUnkQHVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dRhfs8/btrgwCJnW21/KQ3CppdHkiG3TkyUnkQHVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRhfs8%2FbtrgwCJnW21%2FKQ3CppdHkiG3TkyUnkQHVk%2Fimg.png&quot; data-origin-width=&quot;963&quot; data-origin-height=&quot;371&quot; data-filename=&quot;제목 없음.png&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Topic은 일종을 큐 라고 생각을 하시면 됩니다. Producer의 역할은 Topic에 데이터를 삽입을 하며 Consumer의 역할은 Topic에 데이터를 조회 하는 역할을 합니다.&amp;nbsp;Kafka는 아주 유연한 큐 역할을 한다고 보시면 됩니다. 이런 데이터 흐름에 있어서 Kafka는 고가용성으로서 서버가 이슈가 생기거나 갑작스럽게 랙(전원이) 내려간다던가 하는 상황에서도 데이터를 손실없이 복구할 수 있습니다. 또한, Kafka는 낮은 지연과 높은 처리량을 통해서 아주 효과적으로 데이터를 아주 많이 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. Kafka Topic&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka에는 다양한 데이터가 들어갈 수 있는데 데이터가 들어가는 공간을 Topic이라고 합니다. Kafka에서는 Topic을 여러개 생성할 수 있습니다. Topic은 데이터베이스의 테이블이나 파일시스템의 폴더와 유사한 성질을 가지고 있습니다. 이 Topic에 Producer가 데이터를 넣게되고 Consumer는 데이터를 가져가게 됩니다. Topic은 이름을 가질수 있는데 목적에 따라 클릭로그, send sms, location log 등과 같이 무슨 데이터를 담는지 명확하기 명시하면 추후 유지보수 시 편리하게 관리 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Partition이 하나인 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1017&quot; data-origin-height=&quot;447&quot; data-filename=&quot;토픽 파티션 1개.png&quot; width=&quot;646&quot; height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brXrGJ/btrgpwxfxqy/8bRkThPmIbCUMT4ahbVibK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brXrGJ/btrgpwxfxqy/8bRkThPmIbCUMT4ahbVibK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brXrGJ/btrgpwxfxqy/8bRkThPmIbCUMT4ahbVibK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrXrGJ%2Fbtrgpwxfxqy%2F8bRkThPmIbCUMT4ahbVibK%2Fimg.png&quot; data-origin-width=&quot;1017&quot; data-origin-height=&quot;447&quot; data-filename=&quot;토픽 파티션 1개.png&quot; width=&quot;646&quot; height=&quot;284&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 Topic은 여러개의 Partition으로 구성될 수 있으며 첫번째 Partition 번호는 0번부터 시작합니다. 하나의 Partition은 큐와같이 내부에 데이터가 Partition 끝에서부터 차곡차곡 쌓이게 됩니다. 클릭로그 Topic에 Kafka Consumer가 붙게되면 데이터를 가장 오래된 순서대로 가져가게 됩니다. 더이상 데이터가 들어오지 않으면 Consumer는 또 다른 데이터가 들어올때까지 기다립니다. Consumer가 Topic 내부의 Partition에서 데이터를 가져가더라도 데이터는 삭제되지 않고 Partition에 그대로 남게됩니다.&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;만약 Partition #0번의 남은 데이터를 재사용을 하기위해서는 새로운 Consumer가 붙었을때 다시 0번 부터 사용할 수 있습니다. 이를 위해서 몇가지 제약 조건이 있습니다. 첫번째로 Consumer그룹이 달라야하고 auto.offset.reset=earliest 이여야 합니다. 이처럼 사용할 경우 동일 데이터에 대해서 두번 처리할 수 있는데 이는 Kafka를 사용하는 아주 중요한 이유이기도 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Partition이 두개 이상인 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;311&quot; data-filename=&quot;토픽 파티션 2개이상.png&quot; width=&quot;691&quot; height=&quot;209&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhD9Wk/btrgvVbm6oY/Emy8EDGCF3vWpA818ye3uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhD9Wk/btrgvVbm6oY/Emy8EDGCF3vWpA818ye3uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhD9Wk/btrgvVbm6oY/Emy8EDGCF3vWpA818ye3uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhD9Wk%2FbtrgvVbm6oY%2FEmy8EDGCF3vWpA818ye3uK%2Fimg.png&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;311&quot; data-filename=&quot;토픽 파티션 2개이상.png&quot; width=&quot;691&quot; height=&quot;209&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;Partition이 2개 이상인 경우 새로운 데이터가 유입 되었을 때 어떤 Partition으로 보내는 경우는 Producer가 키를 지정 할 수 있습니다. 키가 null 즉, 키를 지정하지 않고 기본 파티셔너 사용한다면 round-robin으로 Partition이 지정됩니다. 반대로 키가 있고 기본 파티셔너를 사용할 경우에는 키의 해시값을 구하고 특정 Partition에 항상 할당되게 됩니다.&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;Partition을 늘리는 것에는 주의해야 할 점이 있습니다. Partition은 늘리는 것은 가능하지만 다시 줄일 수는 없기 때문입니다. Partition을 늘리는 이유는 Partition을 늘리면 Consumer의&amp;nbsp; 개수를 늘려서 데이터 처리를 분산시킬 수 있습니다. 지속적으로 Partition의 데이터가 늘어나면 옵션에 따라 일정 기간 또는 용량 동안 데이터를 저장할 수 있게 되고 적절하게 데이터가 삭제될 수 있도록 설정할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;log.retention.ms : 최대 record 보존 시간&lt;/li&gt;
&lt;li&gt;log.retention.byte : 최대 record 보존 크기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Kafka broker, replication, ISR&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.1 Kafka broker&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka borker는 Kafka가 설치되어 있는 서버 단위를 말합니다. 보통 3개 이상의 borker로 구성하여 사용하는 것을 권장합니다. 만약 Partition이 1개이고 replication이 1인 topic이 존재하고 borker가 3대라면 borker 3대중 1대에 해당 topic의 정보(데이터)가 저장됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.2 Kafka replication&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;replication은 Partition의 복제를 뜻합니다. 만약 replication이 1이라면 Partition은 1개만 존재한다는 것이고 replication이 2라면 Partition은 원본 1개와 복제본 1개로 총 2개가 존재합니다. replication이 3이라면 Partition은 원본 1개와 복제본 2개로 총 3개가 존재하게 됩니다. 다만 borker 개수에 따라서 replication개수가 제한됩니다. borker개수가 3이면 replication은 4가 될수 없습니다. 원본 1개 Partition은 Leader Partition이라고 부릅니다. 그리고 나머지 복제본 Partition은 Follower Partition이라고 부릅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;replication을 사용하는 이유&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;replication은 Partition의 고가용성을 위해 사용됩니다. 만약 borker가 3개인 Kafka에서 replication이 1이고 Partition이 1인 Topic이 존재한다고 가정한다면 borker가 어떠한 이유로 사용불가하게 된다면 더이상 해당 Partition은 복구할 수 없습니다. 만약 replication이 2라면 borker 1개가 죽더라도 Follower Partition이 존재하므로 복제본은 복구가 가능합니다. 나머지 1개가 남은 Follower Partition이 &amp;nbsp;Leader Partition역할을 승계하게 되는 것입니다.&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;* ack&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Producer가 Topic의 Partition에 데이터를 전달할때 전달받는 주체가 Leader Partition입니다. Producer에는 ack라는 상세 옵션이 있습니다. ack를 통해 고가용성을 유지할 수 있는데 이 옵션은 Partition의 replication과 관련이 있습니다. ack는 0, 1, all 옵션 3개중 1개를 골라서 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ack Option 0
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Producer는 &amp;nbsp;Leader Partition에 데이터를 전송하고 응답값을 받지않습니다. 그렇기에 Leader Partition에 데이터가 정상적으로 전송됏는지 그리고 나머지 Partition에 정상적으로 복제되엇는지 알 수 없고 보잘할 수 없기에 속도는 빠르지만 데이터 유실 가능성이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ack Option 1
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Leader Partition에 데이터를 전송하고 Leader Partition이 데이터를 정상적으로 받앗는지 응답값을 받습니다. 다만 나머지 Partition에 복제되엇는지는 알 수 없습니다. 만약 Leader Partition이 데이터를 받는 즉시 broker가 장애가 발생한다면 나머지 Partition에 데이터가 전송되지 못한 상태이므로 데이터의 유실 가능성이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ack Option all
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;1옵션에 추가로 Follower Partition에 복제가 잘 이루어졌는지 응답값을 받습니다. Leader Partition에 데이터를 보낸 후 나머지 Follower Partition에도 데이터가 저장되는 것을 확인하는 절차를 거칩니다. 때문에 속도가 현저히 느리다는 단점이 있습니다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;replication개수가 많아지면 그만큼 broker의 리소스 사용량도 늘어나게 됩니다. 따라서 Kafka에 들어오는 데이터량과 retention data 즉, 저장시간을 잘 생각하여 replication 개수를 정하는 것이 좋습니다. 3개 이상의 브로커를 사용할때&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;replication은 3으로 설정하는 것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.3 Kafka ISR&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 2.2에서 설명한 Leader, Follower Partition을 합쳐서 ISR 즉, In Sync Replica라고 볼 수 있습니다.&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;size18&quot;&gt;&lt;b&gt;3. Kafka Partitioner&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Partitioner는 Kafka Producer의 중요한 개념 중 하나입니다.&amp;nbsp;Producer가 데이터를 보내면 무조건 Partitioner를 통해서 broker로 데이터가 전송됩니다. Partitioner는 데이터를 Topic에 어떤 Partitioner에 넣을지 결정하는 역할을 합니다.&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;레코드에 포함된 메시지 키 또는 메시지 값에 따라서 Partitioner의 위치가 결정되게 됩니다. Producer를 사용하실 때 Partitioner를 따로 설정하지 않으면 UniformStickyPartitioner로 설정이 됩니다. 이 Partitioner는 메시지 키가 있을 때와 없을 때 다르게 동작하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메시지 키가 있는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지 키를 가진 레코드는 Partitioner에 의해서 특정한 해쉬값이 생성됩니다. 이 해쉬값을 기준으로 어느 Partitioner으로 들어갈지 정해지게 됩니다. 동일한 메시지 키를 가진 레코드는 동일한 해쉬값을 만들기 때문에 항상 동일한 Partition에 들어가는 것을 보장합니다. 예를 들어 서울의 온도를 기록하는 레코드를 Partition에 집어넣는다고 가정해볼 수 있습니다. 메세지 키에 &quot;서울&quot;이라는 String 값을 넣고 레코드를 지속적으로 보낸다면 항상 동일한 Partition에 데이터가 순서대로 들어가기 때문에 Consumer는 서울이라는 레코드를 순서를 지켜서 데이터를 처리할 수 있게 되는 것입니다. Partition 한개 내부에서는 큐처럼 동작하기 때문에 순서를 지킬 수 있는것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메시지 키가 없는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지 키가 없는 레코드는 라운드 로빈으로 Partition에 들어가게 됩니다. UniformStickyPartitioner는 Producer에서 배치로 모을 수 있는 최대한의 레코드들을 모아서 Partition으로 데이터를 보내게 됩니다. 이렇게 배치단위로 데이터를 보낼 때 Partition에 round-robin 방식으로 들어가면서 데이터를 넣게 됩니다. 쉽게 말해서 메시지 키가 없는 레코드들은 Partition에 적절히 분배된다고 생각하시면 될 것 같습니다.&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;size18&quot;&gt;&lt;b&gt;4. Kafka Consumer Lag&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka lag은 Kafka를 운영함에 있어서 중요한 모니터링 지표 중 하나입니다.&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;Kafka Producer는 Topic의 Partition에 데이터를 차곡차곡 넣게됩니다. 이 Partition에 데이터가 하나 하나씩 들어가게되면 각 데이터는 오프셋이라고하는 숫자가 붙게됩니다. 만약 Partition이 1개가 존재한다면 Partition이 1개인 Topic에 Producer가 데이터를 넣을 경우 0부터 차례대로 숫자가 매겨지게 됩니다. Producer는 계속해서 데이터를 넣게되고 Consumer는 계속해서 데이터를 가져가게 됩니다. 만약 Producer가 데이터를 넣어주는 속도가 Consumer가 가져가는 속도보다 빠르게 되면 Producer가 넣은 데이터의 오프셋, Consumer가 가져간 데이터의 오프셋 이 두개의 오프셋 간에 차이가 발생합니다. 이게 바로 Consumer Lag입니다. Lag은 적을수도 있고 많을 수도 있습니다. 이 Lag의 숫자를 통해 현재 해당 Topic에 대해 파이프라인으로 연계되어 있는 Producer와 Consumer의 상태에 대해 유추가 가능합니다. Consumer Lag은&amp;nbsp;주로 Consumer의 상태에 대해 볼때 사용합니다.&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;Lag은 각 Partition의 오프셋기준으로 Producer가 넣은 데이터의 오프셋과 Consumer가 가져가는 데이터의 오프셋의 차이를 기반으로 합니다. 그렇기 때문에 Topic에 여러 Partition이 존재할 경우 Lag은 여러개가 존재할 수 잇습니다. 만약 Consumer 그룹이 1개이고 Partition이 2개인 Topic에서 데이터를 가져간다면 Lag은 2개가 측정될 수 있습니다. 이렇게 한개의 Topic과 Consumer&amp;nbsp; 그룹에 대해 Lag이 여러개 존재할 수 있을때 그 중 높은 숫자의 Lag를 records-lag-max라고 부릅니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>느린 거북이</author>
      <guid isPermaLink="true">https://hsti.tistory.com/86</guid>
      <comments>https://hsti.tistory.com/86#entry86comment</comments>
      <pubDate>Fri, 1 Oct 2021 18:25:13 +0900</pubDate>
    </item>
  </channel>
</rss>