<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>사연이 있는 코드</title>
    <link>https://yousrain.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 18 May 2026 06:31:08 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>cjswoduddn</managingEditor>
    <item>
      <title>14. 파드의 컴퓨팅 리소스 관리</title>
      <link>https://yousrain.tistory.com/130</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 파드 컨테이너의 리소스 요청&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파드를 생성할 때 컨테이너가 필요로 하는 CPU와 메모리 양 제한을 지정할 수 있다&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;h3 data-ke-size=&quot;size23&quot;&gt;1.1 리소스 요청을 갖는 파드 생성하기&lt;/h3&gt;
&lt;pre id=&quot;code_1711368511963&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 리소스 요청을 갖는 파드
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    command: [&quot;dd&quot;, &quot;if=/dev/zero&quot;, &quot;of=/dev/null&quot;]
    name: main
    resources:
      requests:
        cpu: 200m
        memory: 10Mi&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너 요청에 cpu 200m과 memory 10Mi를 지정했다&lt;/li&gt;
&lt;li&gt;cpu를 지정하지 않으면 이미 cpu자원이 많이 할당된 경우 자원을 전혀 할당받지 못할 수도 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.11.45 PM.png&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QpoDw/btsF5F8FDVZ/zzg4N5U0elI1ETqgbZeX5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QpoDw/btsF5F8FDVZ/zzg4N5U0elI1ETqgbZeX5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QpoDw/btsF5F8FDVZ/zzg4N5U0elI1ETqgbZeX5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQpoDw%2FbtsF5F8FDVZ%2Fzzg4N5U0elI1ETqgbZeX5K%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;2222&quot; height=&quot;592&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.11.45 PM.png&quot; data-origin-width=&quot;2222&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실습환경은 2코어 머신이므로 컨테이너에 1코어, 즉 50%가 할당된 걸 보여준다&lt;/li&gt;
&lt;li&gt;컨테이너 스펙에 제한이 아닌 요청으로 200m지정했으므로 1코어가 할당될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2 리소스 요청이 스케줄링에 미치는 영향&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.16.23 PM.png&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;1260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u2iKN/btsF5UkkU9P/zCp7WfE3sUPcb1iXcENRN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u2iKN/btsF5UkkU9P/zCp7WfE3sUPcb1iXcENRN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u2iKN/btsF5UkkU9P/zCp7WfE3sUPcb1iXcENRN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu2iKN%2FbtsF5UkkU9P%2FzCp7WfE3sUPcb1iXcENRN0%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;2230&quot; height=&quot;1260&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.16.23 PM.png&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;1260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스케줄러는 파드를 만들 노드를 정할 때 스펙의 요청보다 높은 자원을 가진 노드를 선별한다&lt;/li&gt;
&lt;li&gt;스케줄러는 노드를 정할 때 각 노드에 배포된 파드의 리소스 요청 총량을 확인해서 노드를 정한다(실제사용량 X)&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;스케줄러가 파드를 위해 최적의 노드를 선택할 때 파드의 요청을 사용하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스케줄 가능한 노드 중 최적의 노드를 찾는 알고리즘 LeastRequestedPriority, MostRequestedPriority&lt;/li&gt;
&lt;li&gt;LeastRequestedPriority : 남은 리소스가 가장 큰 노드에 파드를 배정 =&amp;gt; 고른 리소스 분배&lt;/li&gt;
&lt;li&gt;MostRequestedPriority : 남은 리소스가 가장 작은 노드에 파드를 배정 =&amp;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;노드의 용량 검사&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711369721511&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl describe nodes

Capacity
Allocatable&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; Capacity는 노드의 총리소스이며 실제 스케줄 가능 여부는 Allocatable로 결정한다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.00 PM.png&quot; data-origin-width=&quot;2200&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hiq6y/btsF2F90FxW/H5m5Ql8K3OkIHXFoAuUkSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hiq6y/btsF2F90FxW/H5m5Ql8K3OkIHXFoAuUkSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hiq6y/btsF2F90FxW/H5m5Ql8K3OkIHXFoAuUkSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHiq6y%2FbtsF2F90FxW%2FH5m5Ql8K3OkIHXFoAuUkSk%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;2200&quot; height=&quot;554&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.00 PM.png&quot; data-origin-width=&quot;2200&quot; data-origin-height=&quot;554&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.13 PM.png&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6l8qX/btsF548eg0X/ko2bchTkmRcMcZr2kCZHDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6l8qX/btsF548eg0X/ko2bchTkmRcMcZr2kCZHDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6l8qX/btsF548eg0X/ko2bchTkmRcMcZr2kCZHDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6l8qX%2FbtsF548eg0X%2Fko2bchTkmRcMcZr2kCZHDk%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;2192&quot; height=&quot;238&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.13 PM.png&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.26 PM.png&quot; data-origin-width=&quot;2264&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3ZHXm/btsF4Yt0BHC/H7pEVxrZ8kKEj0tJY3zLW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3ZHXm/btsF4Yt0BHC/H7pEVxrZ8kKEj0tJY3zLW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3ZHXm/btsF4Yt0BHC/H7pEVxrZ8kKEj0tJY3zLW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3ZHXm%2FbtsF4Yt0BHC%2FH7pEVxrZ8kKEj0tJY3zLW1%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;2264&quot; height=&quot;228&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.26 PM.png&quot; data-origin-width=&quot;2264&quot; data-origin-height=&quot;228&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.35 PM.png&quot; data-origin-width=&quot;2188&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjMYFu/btsF5ANanH0/FNEzs0TN4yyzJ930Zkkvf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjMYFu/btsF5ANanH0/FNEzs0TN4yyzJ930Zkkvf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjMYFu/btsF5ANanH0/FNEzs0TN4yyzJ930Zkkvf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjMYFu%2FbtsF5ANanH0%2FFNEzs0TN4yyzJ930Zkkvf1%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;2188&quot; height=&quot;940&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.31.35 PM.png&quot; data-origin-width=&quot;2188&quot; data-origin-height=&quot;940&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cpu 800m, memory 20Mi 파드를 하나 생성 후 정상적으로 running하는 모습 확인&lt;/li&gt;
&lt;li&gt;cpu 1, memory 20Mi 파드 추가 생성 요청 시 Pending상태에서 컨테이너가 정상 동작하지 않음&lt;/li&gt;
&lt;li&gt;describe 명령으로 requests-pod-3의 상태를 조회해보면 스케줄이 실패했음을 알 수 있다.&lt;/li&gt;
&lt;li&gt;단, 지금까지 딱 cpu2개로 정확히 할당 가능한 만큼 요청을 했는데 실패한 이유가 있다&lt;/li&gt;
&lt;/ul&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-filename=&quot;Screenshot 2024-03-25 at 9.34.42 PM.png&quot; data-origin-width=&quot;2218&quot; data-origin-height=&quot;1878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt91cJ/btsF3Uei3pX/1VXwuykukNwjAYKxhKEtEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt91cJ/btsF3Uei3pX/1VXwuykukNwjAYKxhKEtEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt91cJ/btsF3Uei3pX/1VXwuykukNwjAYKxhKEtEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt91cJ%2FbtsF3Uei3pX%2F1VXwuykukNwjAYKxhKEtEk%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;2218&quot; height=&quot;1878&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.34.42 PM.png&quot; data-origin-width=&quot;2218&quot; data-origin-height=&quot;1878&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 정의 파드 외에도 kube-system 파드가 자동으로 프로비저닝되어 노드의 자원을 사용하고 있었다.&lt;/li&gt;
&lt;li&gt;두번째 파드를 삭제하면 스케줄러는 삭제를 통지받고 pending 상태의 파드를 스케줄링 할 수 있는지 다시 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.3 CPU 요청이 CPU 시간 공유에 미치는 영향&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.37.07 PM.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHlikq/btsF5t1J0qO/8o3T4SgkcTbvnHWdMloEC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHlikq/btsF5t1J0qO/8o3T4SgkcTbvnHWdMloEC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHlikq/btsF5t1J0qO/8o3T4SgkcTbvnHWdMloEC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHlikq%2FbtsF5t1J0qO%2F8o3T4SgkcTbvnHWdMloEC0%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;2236&quot; height=&quot;1056&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.37.07 PM.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1056&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파드 A는 200m을, 파드 B는 1000m의 CPU요청량이 있고 이는 1:5 비율이다.&lt;/li&gt;
&lt;li&gt;각자 최저 보장 자원을 받은 상태로 프로세스의 CPU사용률이 높아지면 유휴자원을 추가로 할당받는다&lt;/li&gt;
&lt;li&gt;두 파드가 치열하게 경합할 경우 유휴자원은 요청량 비율료 1:5로 할당된다&lt;/li&gt;
&lt;li&gt;만약 경쟁 상황이 아니면 파드 A가 유휴자원 100%를 할당 받을 수 있지만 파드B가 요청하면 바로 자원을 내준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.4 사용자 정의 리소스의 정의와 요청&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;k8s는 사용자 정의 리소스를 노드에 추가하고 파드의 리소스 요청으로 사용자 정의 리소스를 요청할 수 있다.&lt;/li&gt;
&lt;li&gt;노드 오브젝트의 capacity필드에 값을 추가해 값을 인식할 수 있게 한다&lt;/li&gt;
&lt;li&gt;quantity는 정수여야 한다.&lt;/li&gt;
&lt;li&gt;파드스펙에서 resources.requests필드로 지정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 컨테이너에 사용 가능한 리소스 제한&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1 컨테이너가 사용 가능한 리소스 양을 엄격한 제한으로 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줬다 뺏을 수 있는 CPU와 달리 메모리는 한번 주면 반납을 꼭 해야 재활용이 가능한 자원으로 컨테이너마다 메모리 제한이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리소스 제한을 갖는 파드 생성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711370966225&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 리소스 요청을 갖는 파드
apiVersion: v1
kind: Pod
metadata:
  name: requests-pod
spec:
  containers:
  - image: busybox
    command: [&quot;dd&quot;, &quot;if=/dev/zero&quot;, &quot;of=/dev/null&quot;]
    name: main
    resources:
      limits:
        cpu: 1
        memory: 20Mi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리소스 제한 오버커밋&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.50.11 PM.png&quot; data-origin-width=&quot;2202&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QgsE7/btsF17yW3qP/DbDJi8sykFTjZw72IwKrO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QgsE7/btsF17yW3qP/DbDJi8sykFTjZw72IwKrO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QgsE7/btsF17yW3qP/DbDJi8sykFTjZw72IwKrO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQgsE7%2FbtsF17yW3qP%2FDbDJi8sykFTjZw72IwKrO0%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;2202&quot; height=&quot;676&quot; data-filename=&quot;Screenshot 2024-03-25 at 9.50.11 PM.png&quot; data-origin-width=&quot;2202&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최소를 보장하는 리소스 요청과 달리 리소스 제한은 제한의 총량이 자원의 총량보다 많을 수 있다.&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;h3 data-ke-size=&quot;size23&quot;&gt;2.2 리소스 제한 초과&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU는 제한이 있어도 성능과 연결될 뿐 실행에는 문제가 없다&lt;/li&gt;
&lt;li&gt;반면, 메모리는 필요한 만큼 자원을 할당받지 못하면 프로세스가 제동작을 못하므로 프로세스가 종료된다(OOM)&lt;/li&gt;
&lt;li&gt;파드의 재시작 정책이 Always 또는 OnFailure로 설정된 경우 프로세스는 다시 실행된다&lt;/li&gt;
&lt;li&gt;OOM으로 프로세스 재실행이 반복된다면 CrashLoopBackOff상태로 프로세스의 재실행 대기시간을 걸게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 7.31.52 AM.png&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGjglQ/btsF64tiFEv/Lv0skQMx08YFamCXtjbmfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGjglQ/btsF64tiFEv/Lv0skQMx08YFamCXtjbmfk/img.png&quot; data-alt=&quot;OOM으로 종료된 프로세스를 포함한 파드의 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGjglQ/btsF64tiFEv/Lv0skQMx08YFamCXtjbmfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGjglQ%2FbtsF64tiFEv%2FLv0skQMx08YFamCXtjbmfk%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;2208&quot; height=&quot;1100&quot; data-filename=&quot;Screenshot 2024-03-26 at 7.31.52 AM.png&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;OOM으로 종료된 프로세스를 포함한 파드의 상태&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.3 컨테이너의 애플리케이션이 제한을 바라보는 방법&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 7.37.29 AM.png&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5M7hW/btsF5ByBap9/jyszTjaCTliW4J9vPUC41k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5M7hW/btsF5ByBap9/jyszTjaCTliW4J9vPUC41k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5M7hW/btsF5ByBap9/jyszTjaCTliW4J9vPUC41k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5M7hW%2FbtsF5ByBap9%2FjyszTjaCTliW4J9vPUC41k%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;2174&quot; height=&quot;622&quot; data-filename=&quot;Screenshot 2024-03-26 at 7.37.29 AM.png&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;top 명령을 통해 확인한 used, free값은 컨테이너 메모리가 아닌 노드 메모리를 바라본다.&lt;/li&gt;
&lt;li&gt;JVM -Xms 옵션을 설정하지 않은 경우 JVM은 노드 메모리를 기준으로 최대힙을 정하고, 애플리케이션 사용 시 컨테이너 메모리 제한을 초과해 컨테이너에 OOM이 발생할 수 있다.&lt;/li&gt;
&lt;li&gt;-Xms옵션을 설정해도 JVM의 오프 힙 메모리에는 영향을 미치지 않는다(JVM 10 이후 -XX+UseContainerSupport)&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;컨테이너는 노드의 모든 CPU 코어를 본다&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너 CPU제한도 컨테이너가 사용할 수 있는 CPU시간 양을 상대적으로 제한할 뿐이다.&lt;/li&gt;
&lt;li&gt;제한된 CPU코어를 사용하는 애플리케이션에 매우 많은 스레드가 생성되어 그 CPU를 경합할 경우 작업 수행과 메모리 반납이 지연되고 이는 시스템 장애로 이어질 수 있다.&lt;/li&gt;
&lt;li&gt;애플리케이션이 컨테이너 CPU제한을 참조하도록 하기 위해 Downward API를 이용해 그 값을 구할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 파드 QoS 클래스 이해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 제한 총합은 전체 리소스보다 클 수 있고 서로 다른 애플리케이션이 실행될 때 이 값을 초과한 경우가 생길 수 있다. 이때 어떤 파드를 종료시키고 어떤 파드에게 리소스를 할당할지 결정하는 정책이 QoS(Quality of Service)다.&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;BestEffort(최하위 우선순위)&lt;/li&gt;
&lt;li&gt;Burstable&lt;/li&gt;
&lt;li&gt;Guaranteed(최상위 우선순위)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.1 파드의 QoS 클래스 정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; QoS클래스를 파드에 직접 설장하는 게 아닌 파드 컨테이너의 리소스 요청과 제한의 조합에서 파생된다.&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;BestEffort 클래스에 파드를 할당하기&lt;/b&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;li&gt;최악의 경우 CPU를 전혀 할당받지 못한다.&lt;/li&gt;
&lt;li&gt;다른 파드를 위해 즉시 메모리를 해제 후 종료될 수 있다&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;Guaranteed 클래스에 파드 할당하기&lt;/b&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;li&gt;요청을 생략하면 제한과 동일하므로 제한만 설정해도 Guaranteed를 보장한다.&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;Burstable QoS 클래스에 파드 할당하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.11.22 AM.png&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;1046&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tUu2t/btsF3XPHlaN/JAcGEeqWcWtuoiq6Cx98kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tUu2t/btsF3XPHlaN/JAcGEeqWcWtuoiq6Cx98kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tUu2t/btsF3XPHlaN/JAcGEeqWcWtuoiq6Cx98kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtUu2t%2FbtsF3XPHlaN%2FJAcGEeqWcWtuoiq6Cx98kk%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;2156&quot; height=&quot;1046&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.11.22 AM.png&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;1046&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BestEffort와 Guaranteed 사이에 Burstable가 있다.&lt;/li&gt;
&lt;li&gt;리소스제한과 요청이 일치하지 않는 경우, 제한과 요청을 지정하지 않은 컨테이너를 포함한 파드인 경우&lt;/li&gt;
&lt;li&gt;Burstable 파드는 요청한 양만틈의 리소스를 얻지만 필요하면 추가 리소스를 할당받을 수 있다.&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;컨테이너 QoS 클래스 파악&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.17.32 AM.png&quot; data-origin-width=&quot;2290&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cO55Sm/btsF55lOK6w/VyfYDusTjIIeKcoDXUIweK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cO55Sm/btsF55lOK6w/VyfYDusTjIIeKcoDXUIweK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cO55Sm/btsF55lOK6w/VyfYDusTjIIeKcoDXUIweK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcO55Sm%2FbtsF55lOK6w%2FVyfYDusTjIIeKcoDXUIweK%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;2290&quot; height=&quot;998&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.17.32 AM.png&quot; data-origin-width=&quot;2290&quot; data-origin-height=&quot;998&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;&lt;b&gt;다중 컨테이너 파드의 QoS 클래스 파악&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.18.56 AM.png&quot; data-origin-width=&quot;2196&quot; data-origin-height=&quot;870&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MqHJE/btsF4S8sXZO/6hXSio4d7OIs99RtKEhyEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MqHJE/btsF4S8sXZO/6hXSio4d7OIs99RtKEhyEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MqHJE/btsF4S8sXZO/6hXSio4d7OIs99RtKEhyEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMqHJE%2FbtsF4S8sXZO%2F6hXSio4d7OIs99RtKEhyEk%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;2196&quot; height=&quot;870&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.18.56 AM.png&quot; data-origin-width=&quot;2196&quot; data-origin-height=&quot;870&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;다중 컨테이너 파드의 경우 만장일치인 경우만 그 정책대로 가고 한 컨테이너라도 정책이 다르면 Burstable다.&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;h3 data-ke-size=&quot;size23&quot;&gt;3.2 메모리가 부족할 때 어떤 프로세스가 종료되는지 이해&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 오버커밋되면 QoS클래스는 어떤 컨테이너를 먼저 종료할지 결정하고 해제된 리소스를 높은 우선순위 파드에 준다.&lt;/li&gt;
&lt;li&gt;BestEffort를 먼저 종료하고 Burstable, 마지막으로 시스템 프로세스가 메모리를 필요로하면 Guaranteed 파드가 종료된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;QoS 클래스가 우선순위를 정하는 방법 이해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.21.35 AM.png&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1090&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mPJxt/btsF6gtZhOk/wQLEhqHwkIyyyjMYJpPe9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mPJxt/btsF6gtZhOk/wQLEhqHwkIyyyjMYJpPe9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mPJxt/btsF6gtZhOk/wQLEhqHwkIyyyjMYJpPe9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmPJxt%2FbtsF6gtZhOk%2FwQLEhqHwkIyyyjMYJpPe9K%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;2136&quot; height=&quot;1090&quot; data-filename=&quot;Screenshot 2024-03-26 at 8.21.35 AM.png&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1090&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로 클래스의 우선순위 대로 파드의 프로세스를 종료시킨 뒤 자원을 회수한다&lt;/li&gt;
&lt;li&gt;동일한 클래스인 경우 프로세스의 OOM점수를 정하고 가장 높은 프로세스를 종료시킨다.&lt;/li&gt;
&lt;li&gt;위 예시에서 OOM점수는 메모리 요청량 대비 메모리 사용량인 메모리 비율이 높은 파드B를 파드C보다 먼저 kill한 케이스다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 네임스페이스별 파드에 대한 기본 요청과 제한 설정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.1 LimitRange 리소스 소개&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-28 at 1.51.11 PM.png&quot; data-origin-width=&quot;2368&quot; data-origin-height=&quot;1754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8pj4u/btsF78j9a9a/CpKfxfXsrKz6PkqShAd6mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8pj4u/btsF78j9a9a/CpKfxfXsrKz6PkqShAd6mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8pj4u/btsF78j9a9a/CpKfxfXsrKz6PkqShAd6mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8pj4u%2FbtsF78j9a9a%2FCpKfxfXsrKz6PkqShAd6mK%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;2368&quot; height=&quot;1754&quot; data-filename=&quot;Screenshot 2024-03-28 at 1.51.11 PM.png&quot; data-origin-width=&quot;2368&quot; data-origin-height=&quot;1754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 컨테이너 시소스 요청과 제한을 설정하는 대신 LimitRange 리소스를 생성해 이를 수행할 수 있다.&lt;/li&gt;
&lt;li&gt;LimitRange는 컨테이너의 네임스페이스 별 리소스에 최소/최대 제한을 지정하고 명시하지 않으면 디폴트를 지정한다&lt;/li&gt;
&lt;li&gt;LimitRange는 LimitRanger 어드미션 컨트롤 플러그인에서 사용된다&lt;/li&gt;
&lt;li&gt;파드 매니페스트가 API 서버에 게시되면 LimitRanger플로그인이 파드 스펙을 검증한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.2 LimitRange 오브젝트 생성하기&lt;/h3&gt;
&lt;pre id=&quot;code_1711602023168&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# LimitRange

apiVersion: v1
kind: LimitRange
metadata:
  name: poi-limit
spec:
  limits:
  - type: Pod
    min:
      cpu: 50m
      memory: 5Mi
    max:
      cpu: 1
      memory: 1Gi
  - type: Container
    defaultRequest:
      cpu: 100m
      memory: 10Mi
    default:
      cpu: 200m
      memory: 100Mi
    min:
      cpu: 50m
      memory: 5Mi
    max:
      cpu: 1
      memory: 1Gi
    maxLimitRequestRatio:
      cpu: 4
      memory: 10
  - type: PersistentVolumeClaim
    min:
      storage: 1Gi
    max:
      storage: 10Gi&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파드 단위로 리소스 제한을 설정한다&lt;/li&gt;
&lt;li&gt;컨테이너의 기본 리소스 요청과 제한을 지정할 수 있다&lt;/li&gt;
&lt;li&gt;컨테이너의 리소스를 제한하고, cpu와 memory의 비율로 제한을 설정할 수 있다.&lt;/li&gt;
&lt;li&gt;PVC가 요청하는 스토리지의 최대, 최소 용량을 제한할 수 있다.&lt;/li&gt;
&lt;li&gt;LimitRange는 기존 리소스의 제한을 검증하지 않고 이후 생성되는 리소스만 검증한다.&lt;/li&gt;
&lt;li&gt;LimitRange는 본인이 속한 네임스페이스에서만 동작한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.3 강제 리소스 제한&lt;/h3&gt;
&lt;pre id=&quot;code_1711603161301&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kbc create -f pod.yaml
The Pod &quot;poid&quot; is invalid:
* spec.containers[0].resources.requests: Invalid value: &quot;20Gi&quot;: must be less than or equal to memory limit
* spec.containers[0].resources.requests: Invalid value: &quot;1&quot;: must be less than or equal to cpu limit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4.4 기본 리소스 요청과 제한 적용&lt;/h3&gt;
&lt;pre id=&quot;code_1711603346129&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kbc describe po poid

  Limits:
      cpu:     200m
      memory:  100Mi
    Requests:
      cpu:        100m
      memory:     10Mi
      
$ kbc create -f po poid -n poi
$ kbc describe po poid&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파드 manifast에 리소스 요청과 제한을 지정하지 않아도 describe에 내용이 나온다.&lt;/li&gt;
&lt;li&gt;default 네임스페이스가 아닌 poi 네임스페이스에서는 요청과 제한에 대한 내용이 안나온다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;단, LimitRange는 생성되는 개별 파드나 컨테이너에만 적용된다. 즉, 제한에 걸리지 않는 파드가 계속 늘어나면 노드 또는 클러스터 전체 리소스는 한계치까지 사용될 수 있다&lt;/blockquote&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;5. 네임스페이스의 사용 가능한 총 리소스 제한하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.1 ResourceQuota 오브젝트 소개&lt;/h3&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;li&gt;LimitRange와 마찬가지로 기존 생성되어 있던 파드에 대해서는 적용되지 않는다&lt;/li&gt;
&lt;li&gt;리소스쿼터는 네임스페이스에서 파드가 사용할 수 있는 컴퓨팅 리소스양와 PVC 스토리지 양을 제한한다.&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;CPU 및 메모리에 관한 리소스쿼터 생성&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-28 at 3.06.13 PM.png&quot; data-origin-width=&quot;2198&quot; data-origin-height=&quot;876&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpzfhJ/btsGaCYyDCE/21w4KAwYFKBpKRY5jbIm31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpzfhJ/btsGaCYyDCE/21w4KAwYFKBpKRY5jbIm31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpzfhJ/btsGaCYyDCE/21w4KAwYFKBpKRY5jbIm31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpzfhJ%2FbtsGaCYyDCE%2F21w4KAwYFKBpKRY5jbIm31%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;2198&quot; height=&quot;876&quot; data-filename=&quot;Screenshot 2024-03-28 at 3.06.13 PM.png&quot; data-origin-width=&quot;2198&quot; data-origin-height=&quot;876&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1711605893160&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CPU와 메모리에관한 리소스쿼터

apiVersion: v1
kind: ResourceQuota
metadata:
  name: cpu-and-mem
spec:
  hard:
    requests.cpu: 400m
    requests.memory: 200Mi
    limits.cpu: 600m
    limits.memory: 500Mi&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ResouceQuota는 네임스페이스 단위로 적용된다&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;쿼터와 쿼터 사용량 검사&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711606121250&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kbc describe quota

Name:            cpu-and-mem
Namespace:       default
Resource         Used   Hard
--------         ----   ----
limits.cpu       200m   600m
limits.memory    100Mi  500Mi
requests.cpu     100m   400m
requests.memory  10Mi   200Mi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; describe quota를 입력하면 네임스페이스에 허용된 리소스양과 사용중인 리소스양을 확인할 수 있다.&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;리소스쿼터와 함께 LimitRange생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; LimitRange는 단독으로 만들고 적용할 수 있지만 ResourceQuota만 만든 네임스페이스에서 파드는 생성할 수 없다.&lt;/p&gt;
&lt;pre id=&quot;code_1711606295368&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Error from server (Forbidden): error when creating &quot;pod.yaml&quot;: pods &quot;poid&quot; is forbidden: failed quota: cpu-and-mem: must specify limits.cpu,limits.memory,requests.cpu,requests.memory&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.2 퍼시스턴트 스토리지에 관한 쿼터 지정하기&lt;/h3&gt;
&lt;pre id=&quot;code_1711606507464&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 스토리지에 대한 리소스쿼터

apiVersion: v1
kind: ResourceQuota
metadata:
  name: storage
spec:
  hard:
    requests.storage: 500Gi
    ssd.storageclass.storage.k8s.io/requests.storage: 300Gi
    standard.storageclass.storage.k8s.io/requests.storage: 1Ti&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네임스페이스의 모든 스토리지 양은 500Gi로 설정한다&lt;/li&gt;
&lt;li&gt;각 PVC는 특정 스토리지클래스에 프로비저닝할 수 있으므로 각 스토리지 클래스 별로 스토리지 제한을 개별적으로 줄 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.3 생성 가능한 오브젝트 수 제한&lt;/h3&gt;
&lt;pre id=&quot;code_1711606774430&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ResourceQuota
metadata:
  name: objects
spec:
  hard:
    pods: 10
    replicationcontrollers: 5
    secrets: 10
    configmaps: 10
    persistentvolumeclaims: 4
    services: 5
    services.loadbalancers: 1
    services.nodeports: 2
    ssd.storageclass.storage.k8s.io/persistentvolumeclaims: 2&lt;/code&gt;&lt;/pre&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;li&gt;또한 리소스쿼터 자체에 대한 개수를 제한할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5.4 특정 파드 상태나 QoS 클래스에 대한 쿼터 지정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼터는 쿼터범위(BestEffort, NotBestEffort, Terminating, NotTerminating)로 지정해 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;BestEffort는 파드의 QoS가 BestEffort인 파드에, NotBestEffort는 나머지 QoS 클래스를 가진 파드에 적용한다&lt;/li&gt;
&lt;li&gt;Terminating은 파드스펙에 activeDeadlineSeconds가 설정된 파드에 적용된다.&lt;/li&gt;
&lt;li&gt;각 파드가 종료되고 실패로 표시되기 전에 얼마나 오래 실행할 수 있는지 지정할 수 있다.(activeDeadlineSeconds)&lt;/li&gt;
&lt;/ul&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-filename=&quot;Screenshot 2024-03-28 at 3.31.57 PM.png&quot; data-origin-width=&quot;1636&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eo1NbN/btsGbbmaou1/XiwVkIA6TOg5KH6rxoaKW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eo1NbN/btsGbbmaou1/XiwVkIA6TOg5KH6rxoaKW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eo1NbN/btsGbbmaou1/XiwVkIA6TOg5KH6rxoaKW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feo1NbN%2FbtsGbbmaou1%2FXiwVkIA6TOg5KH6rxoaKW1%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;1636&quot; height=&quot;670&quot; data-filename=&quot;Screenshot 2024-03-28 at 3.31.57 PM.png&quot; data-origin-width=&quot;1636&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1711607465201&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# BestEffort/NotTerminating 파드에 대한 리소스쿼터

apiVersion: v1
kind: ResourceQuota
metadata:
  name: besteffort-notterminating-pods
spec:
  scopes:
  - BestEffort
  - NotTerminating
  hard:
    pods: 4&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;scope가 BestEffort가 지정된 경우 리소스에 대한 제한은 지정할 수 없다.&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;6. 파드 리소스 사용량 모니터링&lt;/h2&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;li&gt;예상되는 부하 수준에서 컨테이너의 실제 리소스 사용량을 모니터링해 적정 요청, 제한을 찾아야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6.1 실제 리소스 사용량 수집과 검색&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-03-29 at 10.45.36 AM.png&quot; data-origin-width=&quot;2326&quot; data-origin-height=&quot;1454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1NrKJ/btsGcKIyxsu/adLhfy3qDEIOiCzKiqn0DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1NrKJ/btsGcKIyxsu/adLhfy3qDEIOiCzKiqn0DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1NrKJ/btsGcKIyxsu/adLhfy3qDEIOiCzKiqn0DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1NrKJ%2FbtsGcKIyxsu%2FadLhfy3qDEIOiCzKiqn0DK%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;2326&quot; height=&quot;1454&quot; data-filename=&quot;Screenshot 2024-03-29 at 10.45.36 AM.png&quot; data-origin-width=&quot;2326&quot; data-origin-height=&quot;1454&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cAdvisor 에이전트는 노드에서 실행되는 개별 컨테이너와 노드 전체의 리소스 사용 데이터를 수집한다.&lt;/li&gt;
&lt;li&gt;전체 클러스터에서 이러한 통계를 주앙에서 수집하려면 힙스터라는 추가 구성요소를 실행해야 한다.(최신은 매트릭 서버)&lt;/li&gt;
&lt;li&gt;힙스터는 노드 중 하나에서 파드로 실행되며 쿠버네티스 서비스를 통해 노출돼 IP로 접속이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711677337654&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 매트릭 조회를 위해 필요한 리소스 매니페스트

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
    rbac.authorization.k8s.io/aggregate-to-admin: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-edit: &quot;true&quot;
    rbac.authorization.k8s.io/aggregate-to-view: &quot;true&quot;
  name: system:aggregated-metrics-reader
rules:
- apiGroups:
  - metrics.k8s.io
  resources:
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
rules:
- apiGroups:
  - &quot;&quot;
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  - configmaps
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server-auth-reader
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    k8s-app: metrics-server
  name: system:metrics-server
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  ports:
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        image: k8s.gcr.io/metrics-server/metrics-server:v0.4.2
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /livez
            port: https
            scheme: HTTPS
          periodSeconds: 10
        name: metrics-server
        ports:
        - containerPort: 4443
          name: https
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: https
            scheme: HTTPS
          periodSeconds: 10
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
        volumeMounts:
        - mountPath: /tmp
          name: tmp-dir
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      volumes:
      - emptyDir: {}
        name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  labels:
    k8s-app: metrics-server
  name: v1beta1.metrics.k8s.io
spec:
  group: metrics.k8s.io
  groupPriorityMinimum: 100
  insecureSkipTLSVerify: true
  service:
    name: metrics-server
    namespace: kube-system
  version: v1beta1
  versionPriority: 100&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클러스터 노드의 CPU 및 메모리 사용량 표시&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711677364494&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kbc top node

NAME                              CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
dkosv3-poi-cluster-ingress-5bzg   93m          2%     2786Mi          37%
dkosv3-poi-cluster-master-1       860m         22%    3705Mi          51%
dkosv3-poi-cluster-worker-47hn    112m         2%     3432Mi          46%
dkosv3-poi-cluster-worker-b7cl    119m         3%     3435Mi          46%
dkosv3-poi-cluster-worker-pbbl    259m         6%     3604Mi          48%&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;개별 파드의 CPU와 메모리 사용량 표시&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711677462762&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kbc top pod --all-namespaces

NAMESPACE       NAME                                                  CPU(cores)   MEMORY(bytes)
default         demon-4sxsh                                           1m           244Mi
default         kubia-hostport                                        0m           8Mi
default         pod-add-settime-capability                            0m           0Mi
default         pod-as-user-guest                                     0m           0Mi
default         pod-drop-chown-capability                             0m           0Mi
default         pod-privileged                                        0m           0Mi
default         pod-with-host-network                                 0m           0Mi
default         pod-with-host-network-poi                             0m           0Mi
default         pod-with-host-pid-and-ipc                             0m           0Mi
default         pod-with-readonly-filesystem                          0m           0Mi
default         pod-with-shared-volume-fsgroup                        0m           1Mi
default         pod-with-shared-volume-fsgroup-poi                    0m           2Mi
default         poi-deployment-578dc868d9-cnjsj                       2m           134Mi
default         poi-deployment-578dc868d9-sckpm                       1m           138Mi
default         poi-deployment-578dc868d9-v9m74                       1m           133Mi
default         poid                                                  200m         61Mi
ingress-nginx   ingress-nginx-controller-poi-jrtrf                    3m           93Mi
kakao-system    fluentd-auditlog-pwcdq                                2m           89Mi

...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6.2 기간별 리소스 사용량 통계 저장 및 분석&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;top 명령은 현재 리소스 사용량만 표시해서 기간 별 리소스 집계가 안된다&lt;/li&gt;
&lt;li&gt;일반적으로 집계를 위해 저장은 인플럭스DB를, 시각화를 위해 그라파나를 사용한다&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/130</guid>
      <comments>https://yousrain.tistory.com/130#entry130comment</comments>
      <pubDate>Mon, 25 Mar 2024 21:54:28 +0900</pubDate>
    </item>
    <item>
      <title>[부록1] 각 리소스가 연결되는 방식</title>
      <link>https://yousrain.tistory.com/101</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bE7z7E/btr8PZ565tu/cVKE1UcUB71IzDFPmR4Ktk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bE7z7E/btr8PZ565tu/cVKE1UcUB71IzDFPmR4Ktk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bE7z7E/btr8PZ565tu/cVKE1UcUB71IzDFPmR4Ktk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbE7z7E%2Fbtr8PZ565tu%2FcVKE1UcUB71IzDFPmR4Ktk%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;1280&quot; height=&quot;672&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;** 클러스터마다 연결방식이 상이할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클라이언트와 Ingress Controller(Pod)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인은 Ingress Node의 IP를 매핑했다. 즉, 노드포트로 들어온 클라이언트의 요청이 Ingress Controller라는 파드로 간다. (이것만 확인하면 됨)&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;Ingress Controller와 Ingress&lt;/h3&gt;
&lt;pre id=&quot;code_1681030538466&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl describe ingresses poi-ingress&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;2232&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYeUFH/btr88rHD8nl/4L27kQLOt04BJzDjwBYPC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYeUFH/btr88rHD8nl/4L27kQLOt04BJzDjwBYPC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYeUFH/btr88rHD8nl/4L27kQLOt04BJzDjwBYPC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYeUFH%2Fbtr88rHD8nl%2F4L27kQLOt04BJzDjwBYPC0%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;2232&quot; height=&quot;84&quot; data-origin-width=&quot;2232&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;명령어로 확인해보면 Ingress의 Annotations를 확인할 수 있는데 여기서 kubernetes.io/ingress.class: poi라는 key value가 ingress-controller의 레이블에 있어야 한다. 반드시 key가 kubernetes.io/ingress.class에 대응하는 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Ingress와 Service, Pod&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ingress의 정의부에 Service를 지정하고 Service와 Pod는 레이블로 매핑된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>infrastructure/쿠버네티스 인 액션</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/101</guid>
      <comments>https://yousrain.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 9 Apr 2023 17:58:10 +0900</pubDate>
    </item>
    <item>
      <title>도커 빌드 오류(arm vs amd)</title>
      <link>https://yousrain.tistory.com/100</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 상황&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2023-04-08 at 8.09.05 PM.png&quot; data-origin-width=&quot;2248&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yQT05/btr8Lq4NTm5/jkxrqUmZfPSjnZG4bHjGn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yQT05/btr8Lq4NTm5/jkxrqUmZfPSjnZG4bHjGn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yQT05/btr8Lq4NTm5/jkxrqUmZfPSjnZG4bHjGn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyQT05%2Fbtr8Lq4NTm5%2FjkxrqUmZfPSjnZG4bHjGn0%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;2248&quot; height=&quot;58&quot; data-filename=&quot;Screenshot 2023-04-08 at 8.09.05 PM.png&quot; data-origin-width=&quot;2248&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로 받은 맥북에서 신나는 마음으로 간단한 웹서버를 빌드한 뒤 도커이미지를 만들어 배포했다. 그다음 컨테이너를 실행하는 파드를 만들었는데 위처럼 계속 파드 생성에 실패했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;생각 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 도커를 실행하는 환경 : amd&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 도커를 빌드한 환경 : arm&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;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;pre id=&quot;code_1680952418357&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ docker buildx build --platform=linux/amd64 -t poistargram/port .
$ docker inspect poistargram/port&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2023-04-08 at 8.13.54 PM.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkAiGz/btr8KJ4CwTt/8kEXNdKavnOdRrPQOS7Rc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkAiGz/btr8KJ4CwTt/8kEXNdKavnOdRrPQOS7Rc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkAiGz/btr8KJ4CwTt/8kEXNdKavnOdRrPQOS7Rc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkAiGz%2Fbtr8KJ4CwTt%2F8kEXNdKavnOdRrPQOS7Rc0%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;2236&quot; height=&quot;82&quot; data-filename=&quot;Screenshot 2023-04-08 at 8.13.54 PM.png&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드할 때 실행환경인 amd 기반으로 빌드하도록 옵션을 넣어준다!(간단)&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;arm VS amd&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M1칩은 arm 기반, Intel칩이 amd 기반이다. 이름도 비슷해서 매우 헷갈릴 것 같다.&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;간단하게 해결한 것처럼 적었지만 jdk버전 변경, 파드 에러 로깅 등등 헛다리를 오래 짚어 해결하는 데 4시간은 걸린 것 같다.&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>infrastructure/도커</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/100</guid>
      <comments>https://yousrain.tistory.com/100#entry100comment</comments>
      <pubDate>Sat, 8 Apr 2023 20:20:29 +0900</pubDate>
    </item>
    <item>
      <title>Spring @RequestScope 빈 스코프</title>
      <link>https://yousrain.tistory.com/83</link>
      <description>&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;h2 data-ke-size=&quot;size26&quot;&gt;@RequestScope 사용&lt;/h2&gt;
&lt;pre id=&quot;code_1659855764745&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
@RequestScope
@Setter
@Getter
public class HttpRequest{

    private String headerMessage;
    private int count;

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1659855798271&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@RequiredArgsConstructor
@RequestMapping
@RestController
public class TestController {

    private final HttpRequest request;

    @GetMapping
    public void test(){
        request.setCount(request.getCount()+1);
        log.info(&quot;count : {} &quot;, request.getCount());
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HttpRequest에 @RequestScope 애너테이션을 붙여 스코프를 명시해주고 @Component를 붙여 빈으로 등록해준다. 그다음 빈을 주입받길 원하는 빈 TestController에 원래 하던 것처럼 HttpRequest를 주입해주고 매핑할 메서드에 request의 카운트를 늘려준다.&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;TestController에 주입해준 HttpRequest가 싱글턴이라면 count의 값은 매 요청마다 1씩 늘어나면서 출력할 거고, 매번 새로운 빈이라면 아무리 요청을 계속 넣어도 1만 출력할 거다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.05.00.png&quot; data-origin-width=&quot;3362&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQ2iJg/btrI4UJoMNs/WDHbv4p5LqKW3EW4IoPvgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQ2iJg/btrI4UJoMNs/WDHbv4p5LqKW3EW4IoPvgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQ2iJg/btrI4UJoMNs/WDHbv4p5LqKW3EW4IoPvgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQ2iJg%2FbtrI4UJoMNs%2FWDHbv4p5LqKW3EW4IoPvgk%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;3362&quot; height=&quot;238&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.05.00.png&quot; data-origin-width=&quot;3362&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;curl을 이용해 테스트해보면 count는 계속 1로 찍히는 걸 확인할 수 있다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 곰곰이 생각해보면 TestController에 final키워드로 붙은 HttpRequest에 매번 새로운 빈을 컨테이너가 주입해주는 게 말이 될까? 말 안된다. 로그에 HttpRequest의 해시코드를 추가로 출력해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1659856170352&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@RequiredArgsConstructor
@RequestMapping
@RestController
public class TestController {

    private final HttpRequest request;

    @GetMapping
    public void test(){
        request.setCount(request.getCount()+1);
        log.info(&quot;hashCode : {}, count : {} &quot;, request.hashCode(), request.getCount());
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.09.59.png&quot; data-origin-width=&quot;2126&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGitaQ/btrI2d4hzlA/3smQBPixyUdvJetRFksy90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGitaQ/btrI2d4hzlA/3smQBPixyUdvJetRFksy90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGitaQ/btrI2d4hzlA/3smQBPixyUdvJetRFksy90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGitaQ%2FbtrI2d4hzlA%2F3smQBPixyUdvJetRFksy90%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;2126&quot; height=&quot;180&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.09.59.png&quot; data-origin-width=&quot;2126&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HttpRequest의 해시코드값이 매번 같은 값으로 나온다. 즉, TestController에 최초로 주입된 HttpRequest는 분명 싱글턴으로 동작하고 있다. 생각해보면 curl로 요청이 들어갈 때 HttpRequest의 생명주기가 시작되는데 TestController는 애플리케이션이 부팅되는 시점에 생성되고 그에 맞게 최초 HttpRequest또한 생겨야 정상인 거다.&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;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.41.47.png&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1q12s/btrI3tk1iOO/Y8yH6eGDVXFL5NGysoEkT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1q12s/btrI3tk1iOO/Y8yH6eGDVXFL5NGysoEkT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1q12s/btrI3tk1iOO/Y8yH6eGDVXFL5NGysoEkT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1q12s%2FbtrI3tk1iOO%2FY8yH6eGDVXFL5NGysoEkT0%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;1580&quot; height=&quot;466&quot; data-filename=&quot;스크린샷 2022-08-07 오후 4.41.47.png&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디버거를 통해 주입된 HttpRequest를 까보면 이상한 걸 알 수 있다. 결론부터 말하자면 TestController 에 주입된 HttpRequest는 스프링이 HttpRequest에 붙은 애너테이션 @RequestScope를 보고 프록시 싱글턴빈을 생성해 주입한 빈이다. 실제로 우리가 의도한 대로 사용할 HttpRequest(count = 1을 응답해주는)는 빈 사용 시점까지 생성을 지연시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@RequestScope와 Intercepter를 잘 활용하면 웹 애플리케이션의 유저 별 정보나 로그찍기를 깔끔하게 할 수 있을 것 같다. 다만, 비지니스 코드에 직접 빈을 주입하는 건 스프링에 대한 지식이 많이 필요하므로 부적절한 것 같기도 하다.(애초에 스프링 애너테이션은...?)&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;프록시를 생성하는 과정을 좀 더 파보고 싶지만 이 과정 또한 문맥에 맞게 Lazy Propagation하도록 하자 ^^....&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>spring/core</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/83</guid>
      <comments>https://yousrain.tistory.com/83#entry83comment</comments>
      <pubDate>Sun, 7 Aug 2022 16:48:37 +0900</pubDate>
    </item>
    <item>
      <title>1장 쿠버네티스 소개</title>
      <link>https://yousrain.tistory.com/81</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨테이너의 이해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가상머신&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 단위의 애플리케이션에 각각의 가성머신을 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션의 개수가 많아지면서 하드웨어 리소스, 관리 리소스가 같이 커짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리눅스 컨테이너&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 호스트 시스템에서 여러개의 서비스를 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 다른 환경이지만 가상머신에 비해 리소스가 훨씬 적음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.00.01.png&quot; data-origin-width=&quot;2290&quot; data-origin-height=&quot;1504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjU3gl/btrF5JcpcOZ/8sYE0Xd7EZidLX9X6cuOu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjU3gl/btrF5JcpcOZ/8sYE0Xd7EZidLX9X6cuOu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjU3gl/btrF5JcpcOZ/8sYE0Xd7EZidLX9X6cuOu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjU3gl%2FbtrF5JcpcOZ%2F8sYE0Xd7EZidLX9X6cuOu1%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;2290&quot; height=&quot;1504&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.00.01.png&quot; data-origin-width=&quot;2290&quot; data-origin-height=&quot;1504&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;h2 data-ke-size=&quot;size26&quot;&gt;도커 개념 이해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커는 애플리케이션을 패키징, 배포, 실행하기 위한 플랫폼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션을 전체 환경과 함께 패키징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도커의 주요 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이미지 : 애플리케이션과 환경을 패키징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 레지스트리 : 도커 이미지를 공유하는 클라우드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컨테이너 : 도커 기반 컨테이너 이미지에서 생성된 리눅스 컨테이너&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.08.22.png&quot; data-origin-width=&quot;2660&quot; data-origin-height=&quot;1424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYiEFT/btrF59IHKCA/Fq9RQgKIbnLLCQgKoKUXDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYiEFT/btrF59IHKCA/Fq9RQgKIbnLLCQgKoKUXDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYiEFT/btrF59IHKCA/Fq9RQgKIbnLLCQgKoKUXDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYiEFT%2FbtrF59IHKCA%2FFq9RQgKIbnLLCQgKoKUXDk%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;2660&quot; height=&quot;1424&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.08.22.png&quot; data-origin-width=&quot;2660&quot; data-origin-height=&quot;1424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 개발자는 생성한 이미지를 레포지토리로 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 다른 개발자는 만들어진 이미지를 로컬로 다운&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;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;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.20.13.png&quot; data-origin-width=&quot;2324&quot; data-origin-height=&quot;1114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byo0yu/btrF2MaWCZS/bnxbpH7k56MxsVlaOEuRy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byo0yu/btrF2MaWCZS/bnxbpH7k56MxsVlaOEuRy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byo0yu/btrF2MaWCZS/bnxbpH7k56MxsVlaOEuRy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyo0yu%2FbtrF2MaWCZS%2FbnxbpH7k56MxsVlaOEuRy0%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;2324&quot; height=&quot;1114&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.20.13.png&quot; data-origin-width=&quot;2324&quot; data-origin-height=&quot;1114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 시스템은 마스터와 워커로 구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션 메니피스트를 마스터에 게시하면 마스터가 애플리케이션을 워커노드 클러스터에 배포&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 마스터는 컨트롤 플레인 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 워커는 컨테이너를 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨트롤 플레인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 쿠버네티스 API 서버&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;- Etcd는 분산 데이터 저장소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;워커 노드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너화된 애플리케이션을 실행하는 시스템&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;- API 서버와 통신하고 노드의 컨테이너를 관리하는 Kubelet&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션 네트워크 트래픽을 로드밸런싱하는 쿠버네티스 서비스 프록시(kube-proxy)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.32.05.png&quot; data-origin-width=&quot;2462&quot; data-origin-height=&quot;1774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mbZgw/btrF3LvCSav/pxdR7pqKDjJUrdJnNJmm81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mbZgw/btrF3LvCSav/pxdR7pqKDjJUrdJnNJmm81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mbZgw/btrF3LvCSav/pxdR7pqKDjJUrdJnNJmm81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmbZgw%2FbtrF3LvCSav%2FpxdR7pqKDjJUrdJnNJmm81%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;2462&quot; height=&quot;1774&quot; data-filename=&quot;스크린샷 2022-06-29 오후 10.32.05.png&quot; data-origin-width=&quot;2462&quot; data-origin-height=&quot;1774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 앱디스크립터를 컨트롤 플레인에 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컨트롤 플레인은 앱디스크립터를 해석해서 노드를 스케줄링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 노드에서 필요한 이미지는 도커가 이미지 레지스트리에서 읽어옴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 노드가 활성화되고 컨트롤플레인은 지속적으로 디스크립터 대로 앱이 떠있는지 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션의 복제본 수는 런타임에 변경이 가능&lt;/p&gt;</description>
      <category>infrastructure/쿠버네티스 인 액션</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/81</guid>
      <comments>https://yousrain.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 29 Jun 2022 22:35:01 +0900</pubDate>
    </item>
    <item>
      <title>[mac] java 터미널 버전 변경하기</title>
      <link>https://yousrain.tistory.com/78</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사내에서 사용하는 java 버전은 1.8과 11이다. 각 프로젝트마다 java 버전을 설정해 컴파일할 수 있도록 intellij가 옵션을 제공해서 큰 불편함 없이 사용할 수 있다. 최근에 이러한 걸 크게 신경쓰지 않고 개발하다가 운영환경에서 빌드 할 때 에러를 맛보았다. 바로 프로젝트 빌드 결과물을 외부 저장소에 올릴 때 생긴 문제였다. 로컬에서 컴파일한 .jar파일을 외부에 올리는데 이때 컴파일하는 건 터미널에 설정된 java버전으로 하게 된다. 1.8로 빌드해야할 프로젝트를 11버전으로 빌드한 후 외부저장소에 올리고 그걸 다운받아 사용하는 프로젝트에서 버전이 맞지 않아 컴파일 오류가 발생하게 된 것이다. 서론이 길었는데 시스템의 java 버전을 확인하고 바꾸는 방법을 남겨보자.&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;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.05.46.png&quot; data-origin-width=&quot;2270&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FbSLo/btrxjobgbBf/o0BVkdr44uRaAT1wSw1d51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FbSLo/btrxjobgbBf/o0BVkdr44uRaAT1wSw1d51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FbSLo/btrxjobgbBf/o0BVkdr44uRaAT1wSw1d51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFbSLo%2FbtrxjobgbBf%2Fo0BVkdr44uRaAT1wSw1d51%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;2270&quot; height=&quot;134&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.05.46.png&quot; data-origin-width=&quot;2270&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java -version으로 현재 11버전임을 확인할 수 있다.&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;로컬에 다운로드한 java 버전 확인하기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.06.48.png&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csHoKO/btrxrc9jqki/jEQJLnKYjJ9hkKk2DSD2Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csHoKO/btrxrc9jqki/jEQJLnKYjJ9hkKk2DSD2Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csHoKO/btrxrc9jqki/jEQJLnKYjJ9hkKk2DSD2Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsHoKO%2Fbtrxrc9jqki%2FjEQJLnKYjJ9hkKk2DSD2Tk%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;2268&quot; height=&quot;172&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.06.48.png&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/usr/libexec/java_home -V로 11버전과 1.8버전이 다운로드 되어 있는 걸 확인할 수 있다.&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;java 버전 변경&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.08.24.png&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwUkCd/btrxlqOlPdT/z4rpzkORzQNCeHKMJRKyc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwUkCd/btrxlqOlPdT/z4rpzkORzQNCeHKMJRKyc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwUkCd/btrxlqOlPdT/z4rpzkORzQNCeHKMJRKyc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwUkCd%2FbtrxlqOlPdT%2Fz4rpzkORzQNCeHKMJRKyc1%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;2262&quot; height=&quot;180&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.08.24.png&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;export 명령을 통해 java의 버전을 바꾸었다. 다만, 이 방법은 터미널을 나갔다 들어오면 다시 원래 버전으로 돌아오는 단점이 있다.&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;java 기본버전 변경&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.18.12.png&quot; data-origin-width=&quot;2242&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YyrEM/btrxt0m4wuc/653BpowgEwEZEY1Kp9KEa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YyrEM/btrxt0m4wuc/653BpowgEwEZEY1Kp9KEa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YyrEM/btrxt0m4wuc/653BpowgEwEZEY1Kp9KEa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYyrEM%2Fbtrxt0m4wuc%2F653BpowgEwEZEY1Kp9KEa1%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;2242&quot; height=&quot;164&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.18.12.png&quot; data-origin-width=&quot;2242&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 사용한 버전 확인 명령어로 내 java의 위치를 파악한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.07.png&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca0f8R/btrxt0m4xgA/6qUtep8ipJfRcGSO3KNGJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca0f8R/btrxt0m4xgA/6qUtep8ipJfRcGSO3KNGJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca0f8R/btrxt0m4xgA/6qUtep8ipJfRcGSO3KNGJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca0f8R%2Fbtrxt0m4xgA%2F6qUtep8ipJfRcGSO3KNGJ1%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;2260&quot; height=&quot;52&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.07.png&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에디터로 .bash_profile파일을 열고,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.30.png&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnbd73/btrxrdf8f9B/8GAq8RJBfuWeX7b4extS4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnbd73/btrxrdf8f9B/8GAq8RJBfuWeX7b4extS4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnbd73/btrxrdf8f9B/8GAq8RJBfuWeX7b4extS4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcnbd73%2Fbtrxrdf8f9B%2F8GAq8RJBfuWeX7b4extS4k%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;2230&quot; height=&quot;58&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.30.png&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;export 명령어를 입력해준 뒤&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.58.png&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lVNj1/btrxlp9IINP/3QLLwE36XhMq9FxTEeWTC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lVNj1/btrxlp9IINP/3QLLwE36XhMq9FxTEeWTC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lVNj1/btrxlp9IINP/3QLLwE36XhMq9FxTEeWTC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlVNj1%2Fbtrxlp9IINP%2F3QLLwE36XhMq9FxTEeWTC0%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;2260&quot; height=&quot;196&quot; data-filename=&quot;스크린샷 2022-03-27 오후 12.19.58.png&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;source를 통해 배시를 활성화한 뒤 버전을 확인해주면 끝~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://java.tutorials24x7.com/blog/how-to-switch-java-version-on-mac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://java.tutorials24x7.com/blog/how-to-switch-java-version-on-mac&lt;/a&gt;&lt;/p&gt;</description>
      <category>java</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/78</guid>
      <comments>https://yousrain.tistory.com/78#entry78comment</comments>
      <pubDate>Sun, 27 Mar 2022 12:20:40 +0900</pubDate>
    </item>
    <item>
      <title>Gradle 기본 꿀팁 정리</title>
      <link>https://yousrain.tistory.com/77</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt; gradle 버전 확인하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- gradlew가 있는 디렉토리 경로에서 ./gradlew --version 입력 후 확인&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;gradle의 캐싱&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 실행할 때 gradle은 내부적으로 두 가지 캐시를 먼저 참조한다. 첫번째로 외부라이브러리에 대한 캐시인데 우리가 외부레파지토리에서(nexux, mavenRepository...) 의존성을 다운받은 라이브러리다. 보통 [~/.gradle/cache/modules-2/files-2.1] 경로에 쫙 있는 걸 확인할 수 있다. 다음으로는 내가 작성한 자바파일의 컴파일된 버전이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-12 오후 2.03.05.png&quot; data-origin-width=&quot;2176&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wrW9m/btrvJxt6FEs/yz1J5f9fkkJ4IYpYKKtLdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wrW9m/btrvJxt6FEs/yz1J5f9fkkJ4IYpYKKtLdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wrW9m/btrvJxt6FEs/yz1J5f9fkkJ4IYpYKKtLdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwrW9m%2FbtrvJxt6FEs%2Fyz1J5f9fkkJ4IYpYKKtLdK%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;2176&quot; height=&quot;310&quot; data-filename=&quot;스크린샷 2022-03-12 오후 2.03.05.png&quot; data-origin-width=&quot;2176&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 설정에서 build and run using을 intelliJ IDEA 또는 Gradle로 설정할 수 있는데 intellij로 설정할 경우 프로젝트 디렉토리 하위에 out디렉토리가 생겨 컴파일된 클래스 파일을 캐싱하고, gradle로 설정할 경우 build 또는 target디렉토리에 캐싱을 하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[정리하는 내용이 있을 때마다 추가예정 ^^]&lt;/p&gt;</description>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/77</guid>
      <comments>https://yousrain.tistory.com/77#entry77comment</comments>
      <pubDate>Sat, 12 Mar 2022 14:10:53 +0900</pubDate>
    </item>
    <item>
      <title>[java] 슈퍼타입토큰(super type token)</title>
      <link>https://yousrain.tistory.com/75</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;모든 글은 토비의 봄 채널을 보며 작성하였습니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.youtube.com/watch?v=01sdXvZSjcI&amp;amp;t=1973s&amp;amp;ab_channel=TobyLee&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배경&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-01 오후 2.56.21.png&quot; data-origin-width=&quot;2484&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LKJkc/btrpoVOCG3W/Ezw2KGjluaYsfzkkrorZs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LKJkc/btrpoVOCG3W/Ezw2KGjluaYsfzkkrorZs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LKJkc/btrpoVOCG3W/Ezw2KGjluaYsfzkkrorZs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLKJkc%2FbtrpoVOCG3W%2FEzw2KGjluaYsfzkkrorZs1%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;2484&quot; height=&quot;100&quot; data-filename=&quot;스크린샷 2022-01-01 오후 2.56.21.png&quot; data-origin-width=&quot;2484&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RestTemplate를 사용하다보면 파라미터바인딩을 위한 타입토큰을 넘겨주는 부분에서 생소한 ParameterizedTypeReference를 사용한 걸 볼 수 있다. 클래스 이름과 생김새를 보면 대충 아 바인딩 되길 원하는 타입을 저 안에 넣고 요청을 날리면 되겠구나 싶다. 근데 이상한 건 생성자로 성성했는데 왜 마지막에 {}가 붙냐는 것이다. 이번 기회에 파헤쳐보자.&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;타입토큰(Type Token)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.02.06.png&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;204&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uH3a3/btrpyjHtmEx/uvj2xNDYXa6xDiLCbbGVoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uH3a3/btrpyjHtmEx/uvj2xNDYXa6xDiLCbbGVoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uH3a3/btrpyjHtmEx/uvj2xNDYXa6xDiLCbbGVoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuH3a3%2FbtrpyjHtmEx%2Fuvj2xNDYXa6xDiLCbbGVoK%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;2430&quot; height=&quot;204&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.02.06.png&quot; data-origin-width=&quot;2430&quot; data-origin-height=&quot;204&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RestTemplate을 통해 요청을 보낼 때 그 반환 타입을 타입토큰 형식으로 넘겨주는 걸 볼 수 있다. RestTemplate은 rest api를 이용해 다른 서버에게 요청을 하고 그 내용은 HTTP의 body로 넘어오게 된다(대부분 JSON). 이때 JSON으로 넘어온 값의 key, value를 map에 다시 보관하게 되고 그 map의 내용을 어떤 객체에 바인딩할지 정보가 필요하다. 당연히 RestTemplate에서 메서드롤 호출하는 지점의 반환값으로 런타임에 추측하는 건 말이 안된다. 그러기에 어떤 객체를 바인딩해야할지 정보를 담은 타입토큰을 파라미터로 넘겨주는 것이다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.12.15.png&quot; data-origin-width=&quot;2428&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhdxw6/btrpq8tUCOO/XLDgTP3KYdU2tGKAsKe4a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhdxw6/btrpq8tUCOO/XLDgTP3KYdU2tGKAsKe4a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhdxw6/btrpq8tUCOO/XLDgTP3KYdU2tGKAsKe4a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhdxw6%2Fbtrpq8tUCOO%2FXLDgTP3KYdU2tGKAsKe4a1%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;2428&quot; height=&quot;284&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.12.15.png&quot; data-origin-width=&quot;2428&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 반환받길 원하는 타입이 제네릭을 포함하고 있다면 문제가 된다. 자바의 언어적 이유로(나중에 여유되면 조사) 타입토큰은 제네릭 정보를 포함해서 넘길 수 없다. 말했듯이 메서드 호출 시점에 forObject에 대한 제네릭 타입을 코드에 적어줘도 RestTemplate은 객체 바인딩 시점에 SpecialDto를 바인딩해야함을 알 수 없다. 그래서 실제 forObject의 내부를 디버깅해보면 제네릭으로 SpecialDto가 들어가야할 지점에 LinkedHashMap이 들어가게 된다. 차라리 이게 익셉션을 날리는 구조였으면 나았을 것 같은데 이상하게 실행은 잘되고, 제네릭을 꺼내 쓸 때가 되어야 ClassCastException이 나게 된다.&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;슈퍼타입토큰(Super Type Token)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.32.19.png&quot; data-origin-width=&quot;2434&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cI7SxQ/btrpvTidlOy/i3ok3EkllRwYZMrKUZ0KW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cI7SxQ/btrpvTidlOy/i3ok3EkllRwYZMrKUZ0KW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cI7SxQ/btrpvTidlOy/i3ok3EkllRwYZMrKUZ0KW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcI7SxQ%2FbtrpvTidlOy%2Fi3ok3EkllRwYZMrKUZ0KW0%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;2434&quot; height=&quot;634&quot; data-filename=&quot;스크린샷 2022-01-01 오후 3.32.19.png&quot; data-origin-width=&quot;2434&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결할 방법은 슈퍼타입토큰이다. 위처럼 인스턴스 생성 시점에 제네릭 정보를 넘기는 방식을 살펴보면, 컴파일러가 컴파일 시점에 모든 제네릭 타입을 로타입으로 바꾸고 강제타입캐스팅을 적용한 방식이다. 그래서 타입토큰은 제네릭을 구분하여 보낼 방법이 없는 것이다. 그렇다면 클래스를 제네릭 정보를 포함한 클래스를 상속한 클래스는 그 정보를 갖고 있을까? 갖고 있다. 상속한 클래스가 제네릭정보를 갖고 있다면 그 정보는 런타임에도 접근할 수 있는 정보가 된다. 이제 이 개념을 활용하면 리플렉션을 통해 그 타입을 가져올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 개념을 갖고 위에서 보이는 ParameterizedTypeReference의 생성코드를 보면 상속한 클래스의 타입을 리플렉션해서 필드에 저장하는 걸 확인할 수있다. 단, 이 방식이 유효하려면 인스턴스 ParameterizedTypeReference의 인스턴스를 생성해 리플렉션 하는 게 아닌 ParameterizedTypeReference클래스를 상속한 익명클래스를 만들어서 그 익명클래스를 리플렉션하고 그 안에 있는 제네릭 정보를 빼와야 함을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;AnonymousClass extends ParameterizedTypeReference&amp;lt;GenericDto&amp;lt;SpecialDto&amp;gt; {} ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 위 코드블럭에 나온 AnonymousClass를 리플랙션해야 정확하게 GenericDto속 SpecialDto까지 알아낼 수 있는 것이다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 RestTemplate에서 왜 ParameterizedTypeReference을 넘기는지, 또 왜 생성시점에 {}를 넣어주는지(익명클래스 생성을 위함) 정확하게 알겠다 ^^&lt;/p&gt;</description>
      <category>java</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/75</guid>
      <comments>https://yousrain.tistory.com/75#entry75comment</comments>
      <pubDate>Sat, 1 Jan 2022 16:25:35 +0900</pubDate>
    </item>
    <item>
      <title>Spring 에러 핸들링</title>
      <link>https://yousrain.tistory.com/74</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹애플리케이션 API서버를 만들 때 서버 퀄리티를 결정하는 건 인증과 에러처리라고 생각한다. 인증은 그 방식이 무수히 많고 깊이도 어마어마하지만 인증은(스프링 한정) 어느정도 정형화된 패턴이 있다. 스프링이 어떤 방식으로 에러를 핸들링하는지 그 방식을 커스텀하는 방법은 무엇인지 알아보자^^&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;@ExceptionHandler&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2482&quot; data-origin-height=&quot;552&quot; data-filename=&quot;스크린샷 2021-10-02 오후 12.28.26.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8kudi/btrgAVce5dK/7aQnlGhcnk7gVbvyez18CK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8kudi/btrgAVce5dK/7aQnlGhcnk7gVbvyez18CK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8kudi/btrgAVce5dK/7aQnlGhcnk7gVbvyez18CK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8kudi%2FbtrgAVce5dK%2F7aQnlGhcnk7gVbvyez18CK%2Fimg.png&quot; data-origin-width=&quot;2482&quot; data-origin-height=&quot;552&quot; data-filename=&quot;스크린샷 2021-10-02 오후 12.28.26.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;이런식으로 컨트롤러에서 에러를 핸들링하는 메서드 위에 @ExceptionHandler 에노테이션을 붙여주면 잘 동작한다. 다만, 핸들링을 추가하려면 반드시 컨트롤러 수정이 필요하고 핸들링 범위가 딱 해당 컨트롤러만 적용된다는 점이 단점이다.&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;h2 data-ke-size=&quot;size26&quot;&gt;HandlerExceptionResolver&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spring에서 기본적으로 제공하는 에러핸들러이고 커스텀해서 이용하는 방법도 있다. HandlerExceptionResolver를 구현한 객체를 빈으로 등록하면 스프링의 에러핸들링리스트에 추가되고 조건을 충족하는 경우 발동하는 매카니즘이다. 기본반환형이 ModelAndView여서 json형태로 리턴하려면 MappingJackson2JsonView를 빈으로 등록해줘야한다(이거 동작방식은 추후 조사하는 걸로..^^)&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;2450&quot; data-origin-height=&quot;222&quot; data-filename=&quot;스크린샷 2021-10-02 오후 5.59.27.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blxLuv/btrgCHqI9zP/shnqTtQni5DxcAzhMyyJI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blxLuv/btrgCHqI9zP/shnqTtQni5DxcAzhMyyJI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blxLuv/btrgCHqI9zP/shnqTtQni5DxcAzhMyyJI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblxLuv%2FbtrgCHqI9zP%2FshnqTtQni5DxcAzhMyyJI0%2Fimg.png&quot; data-origin-width=&quot;2450&quot; data-origin-height=&quot;222&quot; data-filename=&quot;스크린샷 2021-10-02 오후 5.59.27.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;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2478&quot; data-origin-height=&quot;550&quot; data-filename=&quot;스크린샷 2021-10-02 오후 5.59.51.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MwJok/btrgBkwf3Vu/knYjZKb8okf95dt6NwONUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MwJok/btrgBkwf3Vu/knYjZKb8okf95dt6NwONUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MwJok/btrgBkwf3Vu/knYjZKb8okf95dt6NwONUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMwJok%2FbtrgBkwf3Vu%2FknYjZKb8okf95dt6NwONUk%2Fimg.png&quot; data-origin-width=&quot;2478&quot; data-origin-height=&quot;550&quot; data-filename=&quot;스크린샷 2021-10-02 오후 5.59.51.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;이러면 모든 컨트롤러에 대해서 발생한 에러는 이 핸들러를 반드시 거치게 된다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 오래된 방식이긴 하지만 핸들링될 에러가 너~무 다양하지 않다면 괜찮은 방식인 것 같다. 관심의 분리 차원에서?? 학부 때라면 열정을 갖고 좀더 세세하게 봤겠지만 주말이라 그런 열정이 안 나온다.. ㅠㅠ 추후 살을 더 붙이는 걸로 가자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>spring/core</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/74</guid>
      <comments>https://yousrain.tistory.com/74#entry74comment</comments>
      <pubDate>Sat, 2 Oct 2021 18:05:51 +0900</pubDate>
    </item>
    <item>
      <title>Git 복잡한 상황 해결</title>
      <link>https://yousrain.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에 다니기 전 혼자 개발할 때는 깃과 깃헙을 단순하게 활용했다. 협엽을 위한 버전관리 도구보다는 그저 ssh를 이용한 클라우드 활용하기 정도였다. 생각없이 커밋, 푸시, PR한 과거를 복구하면서 정리해보자.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개발을 위한 로컬브랜치 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 열심히 개발 및 무지성 커밋(대략 5번, 커밋메세지 무지성 &quot;tmp&quot;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 마스터와 싱크를 맞추기 위해 무지성 git merge master&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- github에 push 후 master에 Pull Request&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp; master와 싱크를 맞추는 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 무지성 커밋과 무지성 메세지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;165&quot; data-filename=&quot;스크린샷 2021-08-04 오후 6.29.47.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJc46b/btrbhZXulQn/3458xv4I46nKOQSz1u2F9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJc46b/btrbhZXulQn/3458xv4I46nKOQSz1u2F9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJc46b/btrbhZXulQn/3458xv4I46nKOQSz1u2F9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJc46b%2FbtrbhZXulQn%2F3458xv4I46nKOQSz1u2F9k%2Fimg.png&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;165&quot; data-filename=&quot;스크린샷 2021-08-04 오후 6.29.47.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;본인만 이해할 법한 그림이지만 어쨌든 문제상황을 만들었다. test/second에서 커밋한 내용을 PR하고 main에 합쳤다. 그리고 main에서 그 내용을 가져왔기 때문에 origin &amp;amp; main이 동일한 레퍼런스를 가리키고 있음을 알 수 있다. 이때 test/first에서 main과 싱크를 맞추기 위해 머지를 한 그림이고 이전에 무지성 3회커밋을 확인할 수 있다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) main과 merge하기 전으로 reset시킨다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 여러 커밋로그를 하나로 rebase하고 의미있는 메세지를 적는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 커밋을 임시로 취소하고 stash를 통해 임시 저장한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) local main에서 origin을 pull해서 main먼저 싱크를 맞춘다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5) 문제의 브랜치를 main으로 reset해서 싱크를 맞춘다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6) stash를 pop하여 깔끔한 상태로 만든 뒤 다시 커밋 후 푸시한다^^&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;h2 data-ke-size=&quot;size26&quot;&gt;1) main과 merge하기 전으로 reset시킨다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 test/first브랜치에서 git log --oneline를 입력하면 아래처럼 커밋 내역을 간단하게 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;248&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4RyQm/btrblj8YUnJ/1yCDUGjvWv5IzmNF6EmGnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4RyQm/btrblj8YUnJ/1yCDUGjvWv5IzmNF6EmGnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4RyQm/btrblj8YUnJ/1yCDUGjvWv5IzmNF6EmGnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4RyQm%2Fbtrblj8YUnJ%2F1yCDUGjvWv5IzmNF6EmGnK%2Fimg.png&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;248&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;git reset --hard lognumber를 통해 간단하게 머지 전으로 돌아가주자&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;2) 여러 커밋로그를 하나로 rebase하고 의미있는 메세지를 적는다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 무지성 커밋 3개를 하나로 합치자. 현재 HEAD로부터 3개를 합치고 싶기 때문에 아래와 같이 입력한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git rebase -i HEAD~3&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2254&quot; data-origin-height=&quot;986&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLvbJy/btra8ALtqsG/axcYsqcDexFraZXWqjFXIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLvbJy/btra8ALtqsG/axcYsqcDexFraZXWqjFXIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLvbJy/btra8ALtqsG/axcYsqcDexFraZXWqjFXIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLvbJy%2Fbtra8ALtqsG%2FaxcYsqcDexFraZXWqjFXIK%2Fimg.png&quot; data-origin-width=&quot;2254&quot; data-origin-height=&quot;986&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;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2232&quot; data-origin-height=&quot;154&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NWPY5/btra8zy3hQL/Knj1BiqOuh4IkfkXKC4Kh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NWPY5/btra8zy3hQL/Knj1BiqOuh4IkfkXKC4Kh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NWPY5/btra8zy3hQL/Knj1BiqOuh4IkfkXKC4Kh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNWPY5%2Fbtra8zy3hQL%2FKnj1BiqOuh4IkfkXKC4Kh1%2Fimg.png&quot; data-origin-width=&quot;2232&quot; data-origin-height=&quot;154&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;참으로 다양한 명령어가 있는데 적절히 읽어보고 사용하면 될 듯하다. 본인은 squash를 이용해 첫 커밋에 이후 두 커밋을 합치겠다. :wp를 통해 작업을 마무리하면 커밋메세지를 다시 작성할 기회를 주니 잘 생각해서 다시 작성해보자. 이후 다시 로그를 확인해보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2240&quot; data-origin-height=&quot;80&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EOQOu/btrbhX6tuuC/uVroi7oK6n1LQDvtBDCOx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EOQOu/btrbhX6tuuC/uVroi7oK6n1LQDvtBDCOx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EOQOu/btrbhX6tuuC/uVroi7oK6n1LQDvtBDCOx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEOQOu%2FbtrbhX6tuuC%2FuVroi7oK6n1LQDvtBDCOx0%2Fimg.png&quot; data-origin-width=&quot;2240&quot; data-origin-height=&quot;80&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;원하는 대로 작업이 된 걸 확인할 수 있다!!&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;3) 커밋을 임시로 취소하고 stash를 통해 임시 저장한다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋에서 취소한 내용을 stash에 보관할 거기 때문에 staged상태로 커밋이 취소되도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git reset --soft HEAD^ (여기서 HEAD^는 현재 HEAD에서 한단계 이전 커밋으로 되돌아감을 말하는 상대경로 개념이다)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2238&quot; data-origin-height=&quot;32&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/99TnU/btra9YemTON/KpjUQ7Gxp769ZyV2U9lohk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/99TnU/btra9YemTON/KpjUQ7Gxp769ZyV2U9lohk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/99TnU/btra9YemTON/KpjUQ7Gxp769ZyV2U9lohk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F99TnU%2Fbtra9YemTON%2FKpjUQ7Gxp769ZyV2U9lohk%2Fimg.png&quot; data-origin-width=&quot;2238&quot; data-origin-height=&quot;32&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;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;332&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYgX3e/btrbkf6RHp1/pup8yPbBCGJeDcwrKhn6x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYgX3e/btrbkf6RHp1/pup8yPbBCGJeDcwrKhn6x0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYgX3e/btrbkf6RHp1/pup8yPbBCGJeDcwrKhn6x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdYgX3e%2Fbtrbkf6RHp1%2Fpup8yPbBCGJeDcwrKhn6x0%2Fimg.png&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;332&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;의도한 대로 HEAD가 바뀌었을 뿐 아니라 이전 커밋내역이 staged상태로 변경된 걸 확인할 수 있다. 이제 stash를 통해 임시 staged 파일들을 임시 저장하도록 하자(git stash, 잘 임시저장했는지 확인은 git stash list)&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;4) local main에서 origin을 pull해서 main먼저 싱크를 맞춘다&lt;/h2&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;h2 data-ke-size=&quot;size26&quot;&gt;5) 문제의 브랜치를 main으로 reset해서 싱크를 맞춘다&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;78&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDnIIh/btrbgpoDY87/1uRLGrgeK4G6510Q7n9RCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDnIIh/btrbgpoDY87/1uRLGrgeK4G6510Q7n9RCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDnIIh/btrbgpoDY87/1uRLGrgeK4G6510Q7n9RCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDnIIh%2FbtrbgpoDY87%2F1uRLGrgeK4G6510Q7n9RCK%2Fimg.png&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;78&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;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;120&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCVATX/btrbkgLsXas/dmGg9b1tZKGzc5qEkakXNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCVATX/btrbkgLsXas/dmGg9b1tZKGzc5qEkakXNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCVATX/btrbkgLsXas/dmGg9b1tZKGzc5qEkakXNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCVATX%2FbtrbkgLsXas%2FdmGg9b1tZKGzc5qEkakXNk%2Fimg.png&quot; data-origin-width=&quot;2260&quot; data-origin-height=&quot;120&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;아주 깔끔하게 싱크가 맞춰진 걸 확인할 수 있다!&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;6) stash를 pop하여 깔끔한 상태로 만든 뒤 다시 커밋 후 푸시한다^^&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2284&quot; data-origin-height=&quot;524&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mAOfq/btrbmxTuHI9/i0UZ8dZvAEPVi92wNrMx11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mAOfq/btrbmxTuHI9/i0UZ8dZvAEPVi92wNrMx11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mAOfq/btrbmxTuHI9/i0UZ8dZvAEPVi92wNrMx11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmAOfq%2FbtrbmxTuHI9%2Fi0UZ8dZvAEPVi92wNrMx11%2Fimg.png&quot; data-origin-width=&quot;2284&quot; data-origin-height=&quot;524&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;이후 add, commit하고 push해주자. 다만, 기존 원격 브랜치와 충돌이 일어나므로 git push -f를 통해 강제 푸시해주자. 주의할 점은 이 방법은 혼자 관리하는 브랜치일 때만 유효하다는 점이다. 절대 누군가가 이 브랜치에서 pull하거나 다른 내용을 작업하고 push한 상태면 안된다. 우리 회사는 이슈 브랜치를 같이 관리하진 않는 듯하니 우선 이방법으로 진행한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Before&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;663&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIg2Dn/btra9Yenm8h/hAnuCusTQUH7TMPkrVK0U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIg2Dn/btra9Yenm8h/hAnuCusTQUH7TMPkrVK0U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIg2Dn/btra9Yenm8h/hAnuCusTQUH7TMPkrVK0U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIg2Dn%2Fbtra9Yenm8h%2FhAnuCusTQUH7TMPkrVK0U0%2Fimg.png&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;663&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;h3 data-ke-size=&quot;size23&quot;&gt;After&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;498&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR47bY/btrbkhcyrJg/lRv7aiOti4CTEQ7rhNkpDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR47bY/btrbkhcyrJg/lRv7aiOti4CTEQ7rhNkpDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR47bY/btrbkhcyrJg/lRv7aiOti4CTEQ7rhNkpDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR47bY%2FbtrbkhcyrJg%2FlRv7aiOti4CTEQ7rhNkpDK%2Fimg.png&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;498&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;&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굉장히 깔끔해진 결과로 바뀜을 알 수 있다. 생각보다 많은 시간을 쏟았다 ㅠㅠ&lt;/p&gt;</description>
      <category>깃 &amp;amp; 깃헙</category>
      <author>cjswoduddn</author>
      <guid isPermaLink="true">https://yousrain.tistory.com/69</guid>
      <comments>https://yousrain.tistory.com/69#entry69comment</comments>
      <pubDate>Wed, 4 Aug 2021 19:12:19 +0900</pubDate>
    </item>
  </channel>
</rss>