<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>70825</title>
    <link>https://hello70825.tistory.com/</link>
    <description>https://github.com/70825</description>
    <language>ko</language>
    <pubDate>Mon, 20 Jul 2026 18:30:54 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>70825</managingEditor>
    <image>
      <title>70825</title>
      <url>https://tistory1.daumcdn.net/tistory/2850074/attach/0ecb844e5e494a859d57442b3848f091</url>
      <link>https://hello70825.tistory.com</link>
    </image>
    <item>
      <title>커피 가공 방식</title>
      <link>https://hello70825.tistory.com/629</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;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;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;- 내추럴 (Natual, 건식)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;건식 방법이라고 불린다. 커피 체리를 선별한 이후에 그대로 바깥에 발효 및 건조시킨다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 체리도 겉껍질, 과육, 점액질이 있는데, 이걸 제거하지 않고 그대로 바깥에 아프리칸 베드에 건조시키기 때문에 관리하기가 어렵다 (벌레 꼬임, 썩을 수도 있음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점은 과육이 남아있기 때문에 단맛, 과일향과 같은 풍미가 느껴진다 (ex. 에티오피아 원두들, ..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점은 날씨, 온도와 같은 외부 요인으로 인해 맛의 편차도 달라지고, 건조할 때 사람이 주기적으로 관리해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;- 워시드 (Washed, 습식)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내추럴 원두 단점을 해결하기 위해 맛의 일관성, 대용량 처리 문제를 해결하기 위해 만들어진 프로세스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Washed 단어처럼 물에 씻는다는 뜻으로 아래 방식으로 물을 많이 활용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 체리 수확 &amp;gt; 물에 두어 커피 체리 선별 &amp;gt; 펄핑 기계로 껍질, 과육 제거 &amp;gt; 발효 탱크에서 발효 &amp;gt; 물로 점액질 세척 &amp;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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;- 허니 (Honey)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내추럴과 워시드 중간에 있는 방식이다.&amp;nbsp;내추럴이 겉껍질, 과육, 점액질을 그대로 남기고, 워시드가 모두 제거하는 방식이라면 허니는 점액질은 그대로 두는 방식이라 내추럴의 단맛과 워시드의 깔끔함을 가져가게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허니 프로세싱은 화이트 허니, 옐로우 허니, 레드 허니, 블랙 허니로 나뉘게 되는데, 점액질을 얼마나 많이 남기냐, 건조할 때 얼마나 자주 뒤집어주냐, 온도는 어떻게 되냐에 따라 달라진다. 허니 프로세싱은 역사 자체가 개인 농장주들이 활용한 방식에서 발전된 기술이라 농장마다 다르다고 하더라. 결국 건조된 원두가 어떤 색깔이냐에 따라 이름이 붙여지는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화이트 허니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 점액질은 거의 제거된 상태로 높은 온도로 건조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 점액질은 100%이나 건조할 때 특정 시간마다 뒤집어줌&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;- 점액질은 100%이나 하루에 한 번 뒤집어줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 펄프드 (Pulped)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 겉껍질과 과육이 제거하고 점액질만 남은 상태로 발효하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허니 프로세싱과 뭐가 다른가 싶은데, 허니보다는 세밀하게 나뉘어져 있지는 않긴하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 디펄프드 (Depulped)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;커피 겉껍질 및 과육 제거 용어가 depulped이다. 그래서 pulped, depulped를 둘 다 같은 용어로 사용하는 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;파나마 로스트 오리진에서 디펄프드 용어로 사용한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- Dry Fermentation&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Washed 방식이 체리를 발효할 때 발효 탱크에서 발효하는데, 외부에 건조된 곳에 발효를 진행하면 Washed (Dry Fermentation)이라는 이름을 붙이게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- Fully Washed, Wet Fermentation&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;워시드 과정중 발효 탱크에서 바로 발효하는 방식 대신 발효 탱크안에 물을 넣어 공기와의 접촉을 완전히 차단 시킨 상태로 발효하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 무산소 (Anaerobic)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무산소는 아프리칸 베드, 발효 탱크 같은 곳에 발효하지 않고, 밀폐된 탱크에서 산소를 차단한 상태로 이산화탄소를 주입해 산소를 밀어내서 발효하는 방식이다. 이산화탄소 대신 질소를 넣으면 Anaerobic 대신 Nitrogen이라고 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- ASD (Anaerobic Slow Dry)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무산소 환경에서 발효한 후 느리게 건조하는 방식이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 탄산 침용 (Carbornic Maceration)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와인에서 사용하는 기술이라고 한다. 무산소 방식이 이산화탄소를 주입하는 방식이라고 나와있는데, 여기서 산소를 빼내게 되면 탄산 침용이다. CM 원두를 먹어보면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;과일향이 강해서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;커피가 아닌 주스를 마시는 느낌도 나고, 처음엔 가향인줄 알았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 질소 침용 (Nitrogen Maceration)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;탄산 침용에서 이산화탄소 대신 질소를 주입하는 방식이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;최근에 시도하는 프로세싱인데 왜 질소를 사용하냐면 CO2가 발효에 개입하고, 질소는 비활성 기체로 발효에 개입하지 않아 발효 환경 변수를 통제하기 위함이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 웨이브 (Wave)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발효 과정에서 온도를 변화시키는 방식이라고 한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 차가운 곳에서 발효하다가, 실온에 발효하면 온도가 변하므로 웨이브 내추럴 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- Light-Deprived Environment&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;햇빛이 들지 않는 곳에서 건조하는 방식이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- Dark Room Dry (DRD)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파나마 라마스투스 패밀리가 만든 방식인데, 햇빛이 들지 않는 어두운 폐쇄된 공간에서 건조하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 통제된 환경으로 일관된 맛을 내기 위해 고안된 방법이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;건조 방식을 세밀하게 제어한다면 제습기를 설치해서 건조한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기도 DRD Natual, DRD Washed 방식이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 저온&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저온 방식은 워시드 밖에 못봤다 (Low Temperature Washed)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워시드 방식이 물에 두어서 발효하는 방식인데, 저온의 물에 두어 발효하는 것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- Dried On Cherry Natural&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커피 체리가 익었을 때, 바로 열매를 따지 않고 더 숙성될 수 있도록 그대로 두는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 저온 발효 (Cold Fermentation)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실온 발효가 아닌 냉장 온도 수준의 온도로 발효하는 방식이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;- 다단계 발효 (Multi-Stage Fermentation)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발효를 여러번 거치는 방식이다. 이때 호기성 발효, 혐기성 발효를 섞어서 진행할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 산화 (Oxidation)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워시드 방식에 추가되는 것인데 펄핑 전후로 산소에 노출시켜 내추럴 특유의 풍미를 어느정도 살린다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지 기술들도 다양하게 있는데, 기술 만든 사람 이름을 붙인다거나.. 호수 물을 사용해서 다른 이름을 붙인다거나.. 무언가 특별한 가공방식은 아니고 저기 위에 있는 내용들에서 벗어나지 않는다&lt;/p&gt;</description>
      <category>공부/etc</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/629</guid>
      <comments>https://hello70825.tistory.com/629#entry629comment</comments>
      <pubDate>Sat, 16 May 2026 08:00:42 +0900</pubDate>
    </item>
    <item>
      <title>백준 서비스 종료 전 마지막 기록</title>
      <link>https://hello70825.tistory.com/627</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/880fT/dJMcaf7kpyF/2GP0GBwHGLVvlHF8k3kJek/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/880fT/dJMcaf7kpyF/2GP0GBwHGLVvlHF8k3kJek/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/880fT/dJMcaf7kpyF/2GP0GBwHGLVvlHF8k3kJek/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F880fT%2FdJMcaf7kpyF%2F2GP0GBwHGLVvlHF8k3kJek%2Fimg.webp&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;354&quot; height=&quot;81&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 처음 100위 달성했을 때 (2019.02.21)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l6DrX/dJMcajohsiF/oRiK6NmcbVwtqlFDqSIvq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l6DrX/dJMcajohsiF/oRiK6NmcbVwtqlFDqSIvq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l6DrX/dJMcajohsiF/oRiK6NmcbVwtqlFDqSIvq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl6DrX%2FdJMcajohsiF%2FoRiK6NmcbVwtqlFDqSIvq0%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;820&quot; height=&quot;290&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;290&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-user-hello70825-2026-04-15-22_25_58 (2).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;2231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biSNw5/dJMcaiXe323/1m8HUfWrtkANgDNgtDkeK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biSNw5/dJMcaiXe323/1m8HUfWrtkANgDNgtDkeK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biSNw5/dJMcaiXe323/1m8HUfWrtkANgDNgtDkeK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiSNw5%2FdJMcaiXe323%2F1m8HUfWrtkANgDNgtDkeK0%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;718&quot; height=&quot;664&quot; data-filename=&quot;screencapture-acmicpc-net-user-hello70825-2026-04-15-22_25_58 (2).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;2231&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;현재는 2046문제를 풀었지만 528위이다&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;스크린샷 2026-04-15 오후 10.28.27.png&quot; data-origin-width=&quot;2360&quot; data-origin-height=&quot;1342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQkKHY/dJMcagZr4Z3/rxqdSU7Zjly1nmBuJ1ChvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQkKHY/dJMcagZr4Z3/rxqdSU7Zjly1nmBuJ1ChvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQkKHY/dJMcagZr4Z3/rxqdSU7Zjly1nmBuJ1ChvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQkKHY%2FdJMcagZr4Z3%2FrxqdSU7Zjly1nmBuJ1ChvK%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;2360&quot; height=&quot;1342&quot; data-filename=&quot;스크린샷 2026-04-15 오후 10.28.27.png&quot; data-origin-width=&quot;2360&quot; data-origin-height=&quot;1342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬으로 진짜 많이 풀었다. 파이썬이 다른 언어에 비해 문법이 간결해서 내 생각대로 코딩하기 너무 편했었다&lt;/p&gt;
&lt;p 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;스크린샷 2026-04-15 오후 11.00.42.png&quot; data-origin-width=&quot;1872&quot; data-origin-height=&quot;1668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsjOen/dJMcaiiFWi5/jRGPc73CmkTma2kO3kVBHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsjOen/dJMcaiiFWi5/jRGPc73CmkTma2kO3kVBHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsjOen/dJMcaiiFWi5/jRGPc73CmkTma2kO3kVBHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsjOen%2FdJMcaiiFWi5%2FjRGPc73CmkTma2kO3kVBHK%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;1872&quot; height=&quot;1668&quot; data-filename=&quot;스크린샷 2026-04-15 오후 11.00.42.png&quot; data-origin-width=&quot;1872&quot; data-origin-height=&quot;1668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. solved.ac&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-solved-ac-profile-hello70825-2026-04-15-22_41_34 (1).png&quot; data-origin-width=&quot;3008&quot; data-origin-height=&quot;6249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2SKYm/dJMcacCMKrq/VyDgy6KZfEPJIiM5OiiMHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2SKYm/dJMcacCMKrq/VyDgy6KZfEPJIiM5OiiMHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2SKYm/dJMcacCMKrq/VyDgy6KZfEPJIiM5OiiMHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2SKYm%2FdJMcacCMKrq%2FVyDgy6KZfEPJIiM5OiiMHk%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;3008&quot; height=&quot;6249&quot; data-filename=&quot;screencapture-solved-ac-profile-hello70825-2026-04-15-22_41_34 (1).png&quot; data-origin-width=&quot;3008&quot; data-origin-height=&quot;6249&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학교 배경 사진은 대회 시작 직전 무작정 사진 동아리 회장님한테 연락해서 사진 좀 달라고 했었다 ㅋㅋㅋ&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이때 좋은 사진이 여러개 있어서 고민하다가 그래도 학교 대회니까 학교 사진을 선택했는데 지금봐도 정말 잘 선택한 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;학교 마스코트인 마하 이미지도 무작정 교직원분한테 전화했는데, 내가 처음으로 학교 교직원이 아닌 학생이 활용한 사례라 서류도 작성하고, 이미지 파일 얻는데 시간이 좀 걸렸다. 좋은 친구들, 선배님, 교수님을 만나 큰 문제 없이 대회를 개최 했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 내가 만든 문제들 (2022년 ~ 2023년)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 제2회 한국항공대 프로그래밍 경진대회 - A. Triathlon &lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(2022년)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&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;screencapture-acmicpc-net-problem-25600-2026-04-15-22_20_14 (1).png&quot; data-origin-width=&quot;2457&quot; data-origin-height=&quot;3557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccrm4N/dJMcaayct1H/BGxnKut6FeEPnJbN4VkbN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccrm4N/dJMcaayct1H/BGxnKut6FeEPnJbN4VkbN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccrm4N/dJMcaayct1H/BGxnKut6FeEPnJbN4VkbN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccrm4N%2FdJMcaayct1H%2FBGxnKut6FeEPnJbN4VkbN1%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;2457&quot; height=&quot;3557&quot; data-filename=&quot;screencapture-acmicpc-net-problem-25600-2026-04-15-22_20_14 (1).png&quot; data-origin-width=&quot;2457&quot; data-origin-height=&quot;3557&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;- 제2회 한국항공대 프로그래밍 경진대회 - F. 입맛이 까다로운 코알라가 유칼립투스 잎을 행복하게 먹을 수 있는 방법&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(2022년)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-problem-25605-2026-04-15-22_34_01 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;5058&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zmsvp/dJMcag6fcmn/eYTENjTGKoy3YiQZq6qt6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zmsvp/dJMcag6fcmn/eYTENjTGKoy3YiQZq6qt6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zmsvp/dJMcag6fcmn/eYTENjTGKoy3YiQZq6qt6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzmsvp%2FdJMcag6fcmn%2FeYTENjTGKoy3YiQZq6qt6K%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;2413&quot; height=&quot;5058&quot; data-filename=&quot;screencapture-acmicpc-net-problem-25605-2026-04-15-22_34_01 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;5058&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제2회 한국항공대 프로그래밍 경진대회 - G. 장마&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(2022년)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span&gt;랑이집사님 덕분에 문제가 나오게 됐다&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-problem-25606-2026-04-15-22_35_18 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3803&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYomzC/dJMcahD3lWQ/fHKfWAkcLcPSsBATdEhLt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYomzC/dJMcahD3lWQ/fHKfWAkcLcPSsBATdEhLt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYomzC/dJMcahD3lWQ/fHKfWAkcLcPSsBATdEhLt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYomzC%2FdJMcahD3lWQ%2FfHKfWAkcLcPSsBATdEhLt0%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;2413&quot; height=&quot;3803&quot; data-filename=&quot;screencapture-acmicpc-net-problem-25606-2026-04-15-22_35_18 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3803&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제3회 한국항공대 프로그래밍 경진대회 - E. 곱하기와 쿼리&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(2023년)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;내가 문제 만들고 내가 실패되어 있다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-problem-28421-2026-04-15-22_38_58 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UFEdw/dJMcacCMKlI/Iah17f8KLxQLMgJVZx8oz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UFEdw/dJMcacCMKlI/Iah17f8KLxQLMgJVZx8oz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UFEdw/dJMcacCMKlI/Iah17f8KLxQLMgJVZx8oz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUFEdw%2FdJMcacCMKlI%2FIah17f8KLxQLMgJVZx8oz1%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;2413&quot; height=&quot;3774&quot; data-filename=&quot;screencapture-acmicpc-net-problem-28421-2026-04-15-22_38_58 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;제3회 한국항공대 프로그래밍 경진대회 - F. XOR 카드게임&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(2023년)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-problem-28422-2026-04-15-22_39_55 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5gxGd/dJMcadVWcw7/90ZyBWYWkedFpV4NAn5oxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5gxGd/dJMcadVWcw7/90ZyBWYWkedFpV4NAn5oxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5gxGd/dJMcadVWcw7/90ZyBWYWkedFpV4NAn5oxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5gxGd%2FdJMcadVWcw7%2F90ZyBWYWkedFpV4NAn5oxK%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;2413&quot; height=&quot;3544&quot; data-filename=&quot;screencapture-acmicpc-net-problem-28422-2026-04-15-22_39_55 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;3544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. Koala 문제집&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃북으로 기초 스터디도 만들고, 방학때는 유튜브 영상 만들어서 코딩테스트 스터디 자료도 만들고 정말 열심히 만들었다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;screencapture-acmicpc-net-group-workbook-9883-2026-04-15-22_56_28 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;4426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uNl7h/dJMcacbHpn7/k9wIfML5g1m74aPAKRnTUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uNl7h/dJMcacbHpn7/k9wIfML5g1m74aPAKRnTUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uNl7h/dJMcacbHpn7/k9wIfML5g1m74aPAKRnTUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuNl7h%2FdJMcacbHpn7%2Fk9wIfML5g1m74aPAKRnTUK%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;2413&quot; height=&quot;4426&quot; data-filename=&quot;screencapture-acmicpc-net-group-workbook-9883-2026-04-15-22_56_28 (1).png&quot; data-origin-width=&quot;2413&quot; data-origin-height=&quot;4426&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;최근에 신규 서비스 개발을 하면서 이진탐색, 차분배열, 누적합 알고리즘을 사용해서 `개발에도 알고리즘이 쓰일 때가 있구나`하고 좋아했는데, 서비스 종료라니 20대의 많은 시간을 보냈던 사이트가 사라진다니 아쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>후기/활동 후기</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/627</guid>
      <comments>https://hello70825.tistory.com/627#entry627comment</comments>
      <pubDate>Sun, 19 Apr 2026 23:46:45 +0900</pubDate>
    </item>
    <item>
      <title>2025 한 일</title>
      <link>https://hello70825.tistory.com/624</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;회사일은 빼고..  &lt;/span&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1. 커피&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;파나마&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파나마 라마스투스 패밀리 엘리다 아구아카테 게이샤 DRD 내추럴 (키헤이 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파나마 로스트 오리진 라스 마가리타스 게이샤 디펄프드 퍼멘테이션 (에어리 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파나마 로스트 오리진 산타 마리아 130-204 게이샤 내추럴 (클라리멘토)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파나마 엘리다 카투아이 asd 내추럴 (에어리 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파나마 아이리스 이스테이트 에이릴 게이샤 CM 워시드 (에어리 커피)&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;size18&quot;&gt;&lt;b&gt;과테말라&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 과테말라 안티구아 워시드 (뉴웨스트 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 과테말라 산타 리타 게이샤 워시드 (헤베 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 과테말라 테라사스 워시드 (커피스니퍼)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;에티오피아&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 예가체프 코케허니 G1 (뉴웨스트 커피, 로스트하우스 허깅)&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;- 에티오피아 손콜레 칼리토 Lot.1 내추럴 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 시다마 아르베고나 부르사 문타샤 무산소 내추럴 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 바샤 베켈레 가토 콜드 퍼멘테이션 7 Days 내추럴 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 게뎁 G1 레쿠 워시드 - 윈터 싱글 오리진 (블루보틀)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 예가체프 아리차 G1 (도조커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 에티오피아 아르베고나 보체사 74158 워시드 (말릭 커피)&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;온두라스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 온두라스 산타 엘레나 카트라차 커뮤니티 (블루보틀)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;콜롬비아&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 콜롬비아 세로 아줄 게이샤 하이브리드 워시드 (로스터릭)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 콜롬비아 엘 타블론 레이트 하베스트 워시드 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 콜롬비아 엘 엔카토 (보난자 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 콜롬비아 CGLE 라스 마가리타스 수단루메 내추럴 (에어리 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 콜롬비아 라스 마가리타스 게이샤 워시드 (언스페셜티 더현대 팝업스토어 - 말릭 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Colombia Aroma Nativo Pink Bourbon EFM 2931 Archers Exclusive Lot (서울카페쇼 - UAE 아처스 커피)&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;size18&quot;&gt;&lt;b&gt;케냐&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 케냐 엠부 은두은두리 피베리 워시드 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 케냐 뚱구리 AB 풀리 워시드 (언스페셜티 더현대 팝업스토어 - 먼스 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 케냐 문가리아 내추럴 ACT 옥션 2위 (언스페셜티 더현대 팝업스토어 - 로우키 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;페루&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 페루 찬차마요 (커피볶는아침)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 페루 페냐 데 레온 게이샤 워시드 (로이스 선물)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 페루 알토 미라도르 게이샤 워시드 (클라리멘토)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;코스타리카&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코스타리카 그라니토스 데 알투라 오르티스 1900 게이샤 레드 허니 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코스타리카 하시엔다 코페이 타카라 #200 게이샤 무산소 워시드 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;니카라과&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 니카라과 라 에스페란사 마라카투라 허니 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;인도네시아&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Aceh Pantan Musara Anoxic (서울카페쇼 - 인도네시아 커먼 그라운드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;블렌딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아몬트 밀크 초콜릿 블렌드 (비로소 커피)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 꽃밭 블렌드 (로스터리 향초)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 빈투바 블렌드 (로스터리 향초)&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;- 헤베커피 6주년 블렌드 (헤베 커피)&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;- 쥬시 블렌드 #2 (로스터리 향초)&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;에티오피아 스카이프로젝트&lt;span&gt; &lt;/span&gt;&lt;/span&gt;언스페셜티 블렌드 (서울카페쇼 - 올웨이즈어거스트)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 썸머 블렌드 (서울카페쇼 - 올웨이즈어거스트)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Npay Dark 75% Roasting (서울카페쇼 - 새턴버드 x 네이버페이)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Npay Dark Plus 90% Roasting (서울카페쇼 - 새턴버드 x 네이버페이)&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;+ 이외에 회사에서 마신 것들 포함하면 추가로 20개는 더 넘게 마신 것 같다&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2. 책&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;기술&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코틀린 인 액션&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 이펙티브 코틀린&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 만들면서 배우는 클린 아키텍처&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 클린 아키텍처&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 가상 면접 사례로 배우는 대규모 시스템 설계 기초 1&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;요즘 개발자를 위한 시스템 설계 수업&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;- 바이브 코딩 너머 개발자 생존법&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt;- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 (읽는 중)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 현장에서 통하는 도메인 주도 설계 실전 가이드 (읽는 중)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;도메인&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 연금 이야기&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 연금 스노우볼 ETF 투자 습관&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 마법의 연금 굴리기&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 단 3개의 미국 ETF로 은퇴하라&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 달러는 왜 비트코인을 싫어하는가?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 스테이블 코인: 머니 리셋&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 전자공시 모르면 주식투자 절대로 하지마라&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 퀄리티 투자 (읽는 중)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;자기계발&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;3. 콘서트, 뮤지컬&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.05.31] 유다빈밴드, 동탄 반석산 피크닉&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.06.14] 팬텀, 뮤지컬&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.08.09] 악동뮤지션 단콘, 악동들&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.08.16] 7 Rock Prime, 락 페스티벌&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.08.30] 실리카겔 단콘, Syn. THE. Size X&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.11.15] 유다빈밴드 단콘, 우리의 밤 - 커튼콜&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.11.22] 한로로 단콘, 자몽살구클럽&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. 마라톤&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.04.19] MBN 선셋 마라톤 5km, 06:20&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.06.07] 서울 희망 마라톤 5km, 06:29&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.09.14] 마블런 10km, 05:40&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.09.21] 안산 마라톤 대회 10km, 05:26&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.10.26] 부산 바다 마라톤 10km, 05:42&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.11.16] MBN 서울 마라톤 10km, 05:24&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- [25.11.23] YTN 서울 투어 마라톤 하프, 06:19&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;5. 개발 활동&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.03.12 ~ 25.06.30] 세종대 그리디 2기 코드리뷰어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.07.04 ~ 25.08.21] 2025 오픈소스 개발자 대회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.09.06] 한국항공대 소학인의 밤&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- [25.09.11 ~ 25.12.31] 세종대 그리디 3기 코드리뷰어&lt;/p&gt;</description>
      <category>후기/활동 후기</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/624</guid>
      <comments>https://hello70825.tistory.com/624#entry624comment</comments>
      <pubDate>Thu, 1 Jan 2026 00:32:28 +0900</pubDate>
    </item>
    <item>
      <title>[후기] 클린 아키텍처</title>
      <link>https://hello70825.tistory.com/616</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9UrxG/btsNlLN4yaD/AfkEleSCoZWWd9KzbnvKJk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9UrxG/btsNlLN4yaD/AfkEleSCoZWWd9KzbnvKJk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9UrxG/btsNlLN4yaD/AfkEleSCoZWWd9KzbnvKJk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9UrxG%2FbtsNlLN4yaD%2FAfkEleSCoZWWd9KzbnvKJk%2Fimg.jpg&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;235&quot; height=&quot;308&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/77283734&quot;&gt;https://www.yes24.com/Product/Goods/77283734&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1744683213937&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;클린 아키텍처 - 예스24&quot; data-og-description=&quot;살아있는 전설이 들려주는 실용적인 소프트웨어 아키텍처 원칙『클린 코드』와 『클린 코더』의 저자이자 전설적인 소프트웨어 장인인 로버트 C. 마틴은 이 책 『클린 아키텍처』에서 이러한 &quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;https://www.yes24.com/Product/Goods/77283734&quot; data-og-url=&quot;https://www.yes24.com/product/goods/77283734&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dvmHUT/hyYChiylPT/XjYeLeokuIC0zNmz3kwJL0/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200,https://scrap.kakaocdn.net/dn/enVkwh/hyYCmEaUzF/AhVIPBJXKxH1VSOM9ymdQ1/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200,https://scrap.kakaocdn.net/dn/bn1KGP/hyYChCUXxv/DdGkVwXMlk2icwBvvcsvOK/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200&quot;&gt;&lt;a href=&quot;https://www.yes24.com/Product/Goods/77283734&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.yes24.com/Product/Goods/77283734&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dvmHUT/hyYChiylPT/XjYeLeokuIC0zNmz3kwJL0/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200,https://scrap.kakaocdn.net/dn/enVkwh/hyYCmEaUzF/AhVIPBJXKxH1VSOM9ymdQ1/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200,https://scrap.kakaocdn.net/dn/bn1KGP/hyYChCUXxv/DdGkVwXMlk2icwBvvcsvOK/img.jpg?width=916&amp;amp;height=1200&amp;amp;face=0_0_916_1200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;클린 아키텍처 - 예스24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;살아있는 전설이 들려주는 실용적인 소프트웨어 아키텍처 원칙『클린 코드』와 『클린 코더』의 저자이자 전설적인 소프트웨어 장인인 로버트 C. 마틴은 이 책 『클린 아키텍처』에서 이러한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 책을 읽은 이유는 &lt;a href=&quot;https://hello70825.tistory.com/612&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;만들면서 배우는 클린 아키텍처&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책을 꾸준히 읽어야하는데, 이미 나에게 도움이 안된다는 사실을 알아버리니 책 읽는 행동 빈도수가 줄어들어서 그만뒀음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5부 중간까지 읽다가 그만뒀어서 지금까지 크게 알게된 점은 다음과 같다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 왜 회사에서 아키텍처 설계하는데 긴 시간을 두고, 코드 작성하는 시간은 상대적으로 짧게 두는지 알 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- SOLID 내용이 한층 더 복잡한 예시로 되어 있다. 객체지향 공부하는 분들에게도 어느정도 도움이 되어 보인다 (근데 워낙 잘 설명된 다른 책들도 많아서..)&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;이 책을 읽으면서 앞으로 어떤 책을 읽어야 시간 대비 효율이 좋을까 고민하게 됐는데, 당장 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;아래 케이스 분들에게 추천한다&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) 만들면서 배우는 클린 아키텍처 코드 = 의존성을 깔끔하게 만들고 싶은 것에 아이디어를 얻어가고 싶다 or 헥사고날에 대해 공부하고 싶다&amp;nbsp;&lt;/p&gt;</description>
      <category>후기/책 후기</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/616</guid>
      <comments>https://hello70825.tistory.com/616#entry616comment</comments>
      <pubDate>Tue, 15 Apr 2025 12:04:18 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] @RequestParam과 @PageableDefault을 동시에 사용할 수 없는 이유</title>
      <link>https://hello70825.tistory.com/615</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.32.31.png&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LNl4z/btsNbdRduUR/7oKPto1KWh8hJBGzXwzuN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LNl4z/btsNbdRduUR/7oKPto1KWh8hJBGzXwzuN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LNl4z/btsNbdRduUR/7oKPto1KWh8hJBGzXwzuN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLNl4z%2FbtsNbdRduUR%2F7oKPto1KWh8hJBGzXwzuN1%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;353&quot; height=&quot;93&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.32.31.png&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;93&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 내용을 알고 있어야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DispatcherServlet의 동작 방식&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; Swagger 문서상에서는 페이지 요청에 필요한 Pageable 값이 필수값으로 적혀 있는데, 쿼리 파라미터 없이 사용해도 데이터를 받을 수 있으니 쿼리 파라미터 없이 요청해도 문제 없냐고 질문 받았다. (번외로 쿼리 파라미터는 size, page, sort인데 왜 Pageable이라고 적혀있는지도..)&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;그래서 필수값이 아닌 것을 명시하기 위해 @RequestParam(required=false)와 @PageableDefault을 동시에 사용하려고 했는데, 이러면 요청시 @PageableDefault이 무시되어 쿼리 파라미터 없이 요청하면 Pageable 값이 들어오지 않아 에러가 발생하는 것이었다.&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;- @RequestParam(required=false)를 통해 Swagger에서는 문서상 필수값이 아님을 보여줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- @PageableDefault(...)를 통해 쿼리 파라미터가 들어오지 않아도 default로 처리 되는게 있었으면 좋겠음&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;그래서 살펴보니 Spring MVC 동작 방식과 관련이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cB7ZXf/btsNaDpslel/kaENDt2wDt64IMiu0gLd9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cB7ZXf/btsNaDpslel/kaENDt2wDt64IMiu0gLd9K/img.png&quot; data-alt=&quot;https://maenco.tistory.com/entry/Spring-MVC-Argument-Resolver%EC%99%80-ReturnValue-Handler&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cB7ZXf/btsNaDpslel/kaENDt2wDt64IMiu0gLd9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcB7ZXf%2FbtsNaDpslel%2FkaENDt2wDt64IMiu0gLd9K%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;779&quot; height=&quot;346&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://maenco.tistory.com/entry/Spring-MVC-Argument-Resolver%EC%99%80-ReturnValue-Handler&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색해보니 중국어된 그림이 주로 나와서 그나마 유의미한 한글로 된 그림을 가지고 왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진에서 중요한 부분은 HandlerAdapter에서 ArgumentResolver를 선택하는 로직이 있는데, 구체적으로 설명하자면 아래 방식으로 동작한다. 이걸 스크린샷으로 하나하나 찍으면 분량이 너무 많으니 궁금한 분들은 아래 내용 보고 IDE 통해서 코드를 보면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사진처럼 요청이 들어오고 HandlerAdapter를 호출한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. HandlerAdapter의 구현체인 RequestMappingHandlerAdapter에서 invokeHandlerMethod(...)를 실행한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. invokeHandlerMethod(...)에서 반환전 가장 마지막 코드인 invocableMethod.invokeAndHandle(...)를 호출한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. invocableMethod는 ServletInvocableHandlerMethod인데 이건 InvocableHandlerMethod를 상속한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. ServleInvocableHanderMethod의 invokeAndHandle(...)는 InvocableHandlerMethod의 invokeForRequest(...)를 호출한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. InvocableHandlerMethod의 InvokeForRequest(...) 내부에서 getMethodArgumentValues(...)를 호출한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. InvocableHandlerMethod의 getMethodArgumentValues(...)는 HandlerMethodArgumentResolverComposite의 supportParameter(...)를 통해 매칭되는 ArgumentResolver가 존재하는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. 이후 InvocableHandlerMethod의 getMethodArgumentValues(...)는 HandlerMethodArgumentResolverComposite의 resolveArgument(...)를 통해 매칭되는 ArgumentResolver를 가져와서 처리한다&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;순서만 봐도 좀 복잡하게 되어있는데, 결론적으로는 7번, 8번 순서에서는 ArgumentResolver를 매칭하는 동작을 하고 있는데, 이때 이 매칭하는 결과값은 &lt;b&gt;파라미터 하나에 ArgumentResolver와 관련된 어노테이션을 하나밖에 매칭하지 못한다&lt;/b&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;스크린샷 2025-04-05 오전 11.23.57.png&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;403&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Rd0B/btsM9Z7Twl3/usD8dvXIluQQ6Qem6q7KNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Rd0B/btsM9Z7Twl3/usD8dvXIluQQ6Qem6q7KNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Rd0B/btsM9Z7Twl3/usD8dvXIluQQ6Qem6q7KNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Rd0B%2FbtsM9Z7Twl3%2FusD8dvXIluQQ6Qem6q7KNK%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;928&quot; height=&quot;403&quot; data-filename=&quot;스크린샷 2025-04-05 오전 11.23.57.png&quot; data-origin-width=&quot;928&quot; data-origin-height=&quot;403&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;여기에서 디버그 모드로 확인해보면 getArguementResolver가 두번씩 호출되는데 7번에서 한 번, 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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 궁금증이 들은 것은 왜 @ReuqestParam 대신 @PageableDefault가 무시될까를 생각해보니 Argument Resolver 저장방식 동작에도 고정된 순서가 있어서 @PageableDefault가 계속 무시되는게 아닐까라는 생각이 들었다.&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;RequestMappingHandlerAdapter에서 afterPropertiesSet() 메서드를 보니 ArgumentResolver의 순서가 정해져있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-04-05 오전 11.18.58.png&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnbl2o/btsNac0d7Ja/1r8DIrTfCgewmgMJSlhwkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnbl2o/btsNac0d7Ja/1r8DIrTfCgewmgMJSlhwkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnbl2o/btsNac0d7Ja/1r8DIrTfCgewmgMJSlhwkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbnbl2o%2FbtsNac0d7Ja%2F1r8DIrTfCgewmgMJSlhwkk%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;1086&quot; height=&quot;554&quot; data-filename=&quot;스크린샷 2025-04-05 오전 11.18.58.png&quot; data-origin-width=&quot;1086&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 data-ke-size=&quot;size16&quot;&gt;처음 스프링 컨테이너가 실행될 때 @Bean, @Component로 되어 있는걸 전부 주입하고, 매핑을 하는데 위 사진처럼 다양한 것들이 세팅된다. 여기서 우리가 볼 곳은 첫 if문인 getDefaultArgumentResolver(...)이다.&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;스크린샷 2025-04-05 오전 11.22.31.png&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVXgNW/btsNa1XLNAT/GESok4nVj5OJEEXCwM3UfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVXgNW/btsNa1XLNAT/GESok4nVj5OJEEXCwM3UfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVXgNW/btsNa1XLNAT/GESok4nVj5OJEEXCwM3UfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVXgNW%2FbtsNa1XLNAT%2FGESok4nVj5OJEEXCwM3UfK%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;950&quot; height=&quot;860&quot; data-filename=&quot;스크린샷 2025-04-05 오전 11.22.31.png&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;860&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;여기 순서대로 ArgumentResolver가 추가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@RequestParam의 경우에는 첫번째로 등록되는 RequestParamMethodArgumentResolver로 등록이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@PageableDefault는 세가지 경우로 Resolver가 처리된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 아무것도 건들지 않았을 경우&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spring-data-jpa 의존성이 있다면 SpringDataWebConfiguration이라는 곳에서 관련 Resolver를 자동으로 추가해준다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진에서 AuthArgumentResolver를 제외한 나머지 3개의 리졸버가 SpringDataWebConfiguration에서 등록된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.27.48.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYvTxk/btsM9BGuH0F/0d9HY4HL9KF62W5iJA9MJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYvTxk/btsM9BGuH0F/0d9HY4HL9KF62W5iJA9MJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYvTxk/btsM9BGuH0F/0d9HY4HL9KF62W5iJA9MJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYvTxk%2FbtsM9BGuH0F%2F0d9HY4HL9KF62W5iJA9MJ1%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;800&quot; height=&quot;201&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.27.48.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) PageableHandelrMethodArgumentResolver를 사용해 커스텀해서 Configuration에 등록할 경우&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.30.26.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOhlTy/btsNbhstY2M/HD76bA94OS1Lv6AzW0J0ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOhlTy/btsNbhstY2M/HD76bA94OS1Lv6AzW0J0ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOhlTy/btsNbhstY2M/HD76bA94OS1Lv6AzW0J0ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOhlTy%2FbtsNbhstY2M%2FHD76bA94OS1Lv6AzW0J0ck%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;847&quot; height=&quot;170&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.30.26.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;170&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;1번이 저장된 상황에서 2번이 저장된다면 1번과 충돌이 날테니 1번이 무시되고 커스텀한 리졸버 1개가 등록된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) PageableHandlerMethodArgumentResolver를 커스텀 했으나 Configuration에 등록되지 않은 경우&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커스텀을 만들었는데, 등록을 하지 않아도 1번이 무시된다. 그냥 PageableHandlerMethodArgumentResovler가 쓰이는 곳이 있으면 무조건 넘어가게 만든 것으로 보인다. Resolver 등록 로직 마지막에 ServletModelAttributeMethodProcessor가 있는데, 여기랑 연결이 되어서 Pageable과 바인딩이 되지 않아 에러가 발생한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.12.15.png&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;185&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmRBlm/btsNaDiK38a/JAOBhWAcM10QXx1xtUAerK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmRBlm/btsNaDiK38a/JAOBhWAcM10QXx1xtUAerK/img.png&quot; data-alt=&quot;ModelAttributeMethodProccessor 내부에 Binder가 존재함&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmRBlm/btsNaDiK38a/JAOBhWAcM10QXx1xtUAerK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmRBlm%2FbtsNaDiK38a%2FJAOBhWAcM10QXx1xtUAerK%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;1147&quot; height=&quot;185&quot; data-filename=&quot;스크린샷 2025-04-05 오후 12.12.15.png&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;185&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ModelAttributeMethodProccessor 내부에 Binder가 존재함&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;별거 아닌 질문이었는데 너무 복잡하다&lt;/p&gt;</description>
      <category>백엔드/Spring</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/615</guid>
      <comments>https://hello70825.tistory.com/615#entry615comment</comments>
      <pubDate>Sat, 5 Apr 2025 12:35:43 +0900</pubDate>
    </item>
    <item>
      <title>[후기] 만들면서 배우는 클린 아키텍처</title>
      <link>https://hello70825.tistory.com/612</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWOYBH/btsMtH6TiLR/aMR5F64kE17uHObFacvvFK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWOYBH/btsMtH6TiLR/aMR5F64kE17uHObFacvvFK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWOYBH/btsMtH6TiLR/aMR5F64kE17uHObFacvvFK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWOYBH%2FbtsMtH6TiLR%2FaMR5F64kE17uHObFacvvFK%2Fimg.jpg&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;242&quot; height=&quot;323&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에 &lt;a href=&quot;https://youngseo-computerblog.tistory.com/168&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지인&lt;/a&gt;에게 추천 받아 바로 구매해서 지하철 타고 출근하는동안 틈틈히 읽은 책, 분량이 150페이지라서 마음만 먹으면 주말 하루안에 읽을 수도 있는 책이다.&lt;br /&gt;&lt;br /&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;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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;솔직히 헥사고날 내용은 내 상황에서 굳이 공부하지 않아도 되는 내용이지만, 그래도 레이어드 아키텍처의 아쉬운 점이 무엇인지 설명해주고, 이 문제점을 해결하기위해 어떤 내용이 첨가했는지 공부한건 유익한 것 같다. 다만 내가 진짜 원하는 내용을 얻으려면 클린아키텍처 책을 읽어야 유용할듯. 책에 현재 업무를 이해하는데 도움이 되는 내용도 있지만, 내용이 클린 아키텍처가 아니라 거의 헥사고날에 치중되어 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;책의 장점으로는 처음에 헥사고날 구조를 보고, 내가 상상 코딩을 하면 도대체 어떻게 만들어야할까라는 막막함부터 들었다. 예를 들어서 adaptor, port, usecase 개념을 조금 알아도 '이걸 어떻게 코드로 작성할건데?' 하면 긴 시간을 고민해야 만들 수 있을까하는 수준으로 보인다. 이 책에서는 너무 떠먹는 수준의 코드까지 세세하게는 설명해주는 자료는 많지 않고 (그래서 분량이 적게 만들어질 수 있었는듯), 내가 충분히 생각할 수 있을 수준의 자료만 주어져서 책을 읽으면서 성장이 되는 느낌이 많이 들었다. 대신 한 페이지 넘기는데 좀 시간이 걸렸다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 책을 읽을만한 사람은 클린아키텍처 책은 너무 두꺼워서 읽기 거부감이 드는데, 헥사고날이 왜 나오게 됐는지 알아보고 싶은 사람에게 좋다. 특히 분량이 작아서 금방 해치울 수 있을 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래 링크는 책 다 읽고 발표 스터디를 진행한 내용이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740898199452&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Backend-Study/WEEK26/111. 만들면서 배우는 클린 아키텍처를 읽고 at master &amp;middot; kauKoala/Backend-Study&quot; data-og-description=&quot;Contribute to kauKoala/Backend-Study development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&quot; data-og-url=&quot;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dkPIZM/hyYjubqN3u/IoLVhBGGGpwqU9Q81NA6xk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/i8r4h/hyYmS9vEig/RcElp93lMVUKEIBgNHlYyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/4vZya/hyYjy5SH4P/wHEsqcgnQoKJxCQLMqlkI1/img.png?width=956&amp;amp;height=470&amp;amp;face=0_0_956_470&quot;&gt;&lt;a href=&quot;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kauKoala/Backend-Study/tree/master/WEEK26/111.%20%EB%A7%8C%EB%93%A4%EB%A9%B4%EC%84%9C%20%EB%B0%B0%EC%9A%B0%EB%8A%94%20%ED%81%B4%EB%A6%B0%20%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A5%BC%20%EC%9D%BD%EA%B3%A0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dkPIZM/hyYjubqN3u/IoLVhBGGGpwqU9Q81NA6xk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/i8r4h/hyYmS9vEig/RcElp93lMVUKEIBgNHlYyk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/4vZya/hyYjy5SH4P/wHEsqcgnQoKJxCQLMqlkI1/img.png?width=956&amp;amp;height=470&amp;amp;face=0_0_956_470');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Backend-Study/WEEK26/111. 만들면서 배우는 클린 아키텍처를 읽고 at master &amp;middot; kauKoala/Backend-Study&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to kauKoala/Backend-Study development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tech.kakaopay.com/post/home-hexagonal-architecture/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tech.kakaopay.com/post/home-hexagonal-architecture/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740661372560&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Hexagonal Architecture, 진짜 하실 건가요? | 카카오페이 기술 블로그&quot; data-og-description=&quot;카카오페이 홈 서버 개편 후 운영 과정에서 Hexagonal Architecture 아키텍처 적용, 제거 경험을 공유합니다.&quot; data-og-host=&quot;tech.kakaopay.com&quot; data-og-source-url=&quot;https://tech.kakaopay.com/post/home-hexagonal-architecture/&quot; data-og-url=&quot;https://tech.kakaopay.com/post/home-hexagonal-architecture/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bquk2w/hyYjrekZqe/gjXTZa0vxCMkJzOZ3eiGz0/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/Gdbt8/hyYjGJi1ts/kZes0F0UX4p2UR2EUy0YfK/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319&quot;&gt;&lt;a href=&quot;https://tech.kakaopay.com/post/home-hexagonal-architecture/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tech.kakaopay.com/post/home-hexagonal-architecture/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bquk2w/hyYjrekZqe/gjXTZa0vxCMkJzOZ3eiGz0/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319,https://scrap.kakaocdn.net/dn/Gdbt8/hyYjGJi1ts/kZes0F0UX4p2UR2EUy0YfK/img.png?width=480&amp;amp;height=319&amp;amp;face=0_0_480_319');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Hexagonal Architecture, 진짜 하실 건가요? | 카카오페이 기술 블로그&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;카카오페이 홈 서버 개편 후 운영 과정에서 Hexagonal Architecture 아키텍처 적용, 제거 경험을 공유합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tech.kakaopay.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1740840954717&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;유일한 멀티모듈 헥사고날 아키텍처 : 메시지 허브 적용기&quot; data-og-description=&quot;안녕하세요, 카카오뱅크 고객인증개발팀 서버개발자 Kj입니다. 이번 글에서는 카카오뱅크의 메시지 허브 시스템에 적용된 멀티모듈 헥사고날 아키텍처 사례를 소개합니다. 헥사고날 아키텍처&quot; data-og-host=&quot;tech.kakaobank.com&quot; data-og-source-url=&quot;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&quot; data-og-url=&quot;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Dyh22/hyYmMBn5yL/cz2nPffPjIlak82mSVlpA0/img.png?width=1201&amp;amp;height=631&amp;amp;face=0_0_1201_631,https://scrap.kakaocdn.net/dn/cf1XvN/hyYm5OrYSp/cSKOKoRJcEWA1M3HyTydnk/img.png?width=1000&amp;amp;height=563&amp;amp;face=0_0_1000_563&quot;&gt;&lt;a href=&quot;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tech.kakaobank.com/posts/2311-hexagonal-architecture-in-messaging-hub/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Dyh22/hyYmMBn5yL/cz2nPffPjIlak82mSVlpA0/img.png?width=1201&amp;amp;height=631&amp;amp;face=0_0_1201_631,https://scrap.kakaocdn.net/dn/cf1XvN/hyYm5OrYSp/cSKOKoRJcEWA1M3HyTydnk/img.png?width=1000&amp;amp;height=563&amp;amp;face=0_0_1000_563');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;유일한 멀티모듈 헥사고날 아키텍처 : 메시지 허브 적용기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요, 카카오뱅크 고객인증개발팀 서버개발자 Kj입니다. 이번 글에서는 카카오뱅크의 메시지 허브 시스템에 적용된 멀티모듈 헥사고날 아키텍처 사례를 소개합니다. 헥사고날 아키텍처&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tech.kakaobank.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/g6Tg6_qpIVc?si=3DimusT1c4YLJm48&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/g6Tg6_qpIVc?si=3DimusT1c4YLJm48&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=g6Tg6_qpIVc&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/0il15/hyYm8qBbpZ/EhiAU1UGxQChVktCK1a3DK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=986_174_1146_348,https://scrap.kakaocdn.net/dn/rJnKP/hyYjAvx0NT/03dUsmM3gJZJk6OlI7din0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=986_174_1146_348&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;[NHN FORWARD 22] 클린 아키텍처 애매한 부분 정해 드립니다.&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/g6Tg6_qpIVc&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&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>후기/책 후기</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/612</guid>
      <comments>https://hello70825.tistory.com/612#entry612comment</comments>
      <pubDate>Sun, 2 Mar 2025 15:52:05 +0900</pubDate>
    </item>
    <item>
      <title>[후기] 코틀린 인 액션</title>
      <link>https://hello70825.tistory.com/607</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001804588&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://product.kyobobook.co.kr/detail/S000001804588&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1736861600961&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Kotlin in Action | 드미트리 제메로프 - 교보문고&quot; data-og-description=&quot;Kotlin in Action | 코틀린이 안드로이드 공식 언어가 되면서 관심이 커졌다. 이 책은 코틀린 언어를 개발한 젯브레인의 코틀린 컴파일러 개발자들이 직접 쓴 일종의 공식 서적이라 할 수 있다. 코틀&quot; data-og-host=&quot;product.kyobobook.co.kr&quot; data-og-source-url=&quot;https://product.kyobobook.co.kr/detail/S000001804588&quot; data-og-url=&quot;https://product.kyobobook.co.kr/detail/S000001804588&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gRauS/hyX0v1689a/xXKNpIVmPFBipIZujYFY8k/img.jpg?width=458&amp;amp;height=573&amp;amp;face=0_0_458_573,https://scrap.kakaocdn.net/dn/ywXZV/hyX0pU67CU/Ai75vfQs64F9RcUTnPmhw0/img.jpg?width=458&amp;amp;height=573&amp;amp;face=0_0_458_573&quot;&gt;&lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001804588&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://product.kyobobook.co.kr/detail/S000001804588&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gRauS/hyX0v1689a/xXKNpIVmPFBipIZujYFY8k/img.jpg?width=458&amp;amp;height=573&amp;amp;face=0_0_458_573,https://scrap.kakaocdn.net/dn/ywXZV/hyX0pU67CU/Ai75vfQs64F9RcUTnPmhw0/img.jpg?width=458&amp;amp;height=573&amp;amp;face=0_0_458_573');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Kotlin in Action | 드미트리 제메로프 - 교보문고&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Kotlin in Action | 코틀린이 안드로이드 공식 언어가 되면서 관심이 커졌다. 이 책은 코틀린 언어를 개발한 젯브레인의 코틀린 컴파일러 개발자들이 직접 쓴 일종의 공식 서적이라 할 수 있다. 코틀&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;product.kyobobook.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책 내용은  팀 코드에 사용되지 않은 내용은 효율상 건너뛴 것도 쬐끔 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에 대한 평가를 간단하게 요약해보자면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[1] 자바 유경험자에게 추천하는 기본서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 책 초반부부터 마지막까지 자바와 비교하는 내용이 꽤 있어서 자바 공부한 사람이 공부하기 쉽다. 특히 자바 코드, 코틀린 코드로 비교하는 곳은 딱딱 이해가 잘 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자바의 정석은 자바 8 내용까지 나와있어서 이후 버전에 새로 나온 키워드들이 적혀있지 않지만, 코틀린은 sealed 키워드까지 책에 나오는거 보고 기본적인건 다 있겠다고 느껴졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2] 두고두고 봐야하는 기본서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 코틀린에서만 제공하는 문법은 숙련자에게는 편해보이지만, 초보자에겐 어려워보인다. 이에 걸맞게 책 내용도 어렵고 활용처가 감이 안잡히는 것도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3] 1판이라 아쉬움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 1판은 코루틴 내용이 부록으로 간단하게 나와있어서 아쉬웠다. 내용도 경량 스레드에 대해 찾아본 사람이면 굳이 안읽어도 되는 분량이다. 2판은 코루틴 내용이  보강될거라는데 작년 4월에 원서 출판을 해서 한국어로 번역하는데 시간이 좀 걸릴 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(찾아보니 25/02/27에 나오는듯 싶다)&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>
      <category>후기/책 후기</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/607</guid>
      <comments>https://hello70825.tistory.com/607#entry607comment</comments>
      <pubDate>Wed, 5 Feb 2025 22:51:54 +0900</pubDate>
    </item>
    <item>
      <title>[Network] GSLB (Global Server Load Balancing)</title>
      <link>https://hello70825.tistory.com/610</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-01-31 오후 6.30.43.png&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;131&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfxjXs/btsL4EQmVKu/VkJkYvLClRh0aFO9lAoUo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfxjXs/btsL4EQmVKu/VkJkYvLClRh0aFO9lAoUo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfxjXs/btsL4EQmVKu/VkJkYvLClRh0aFO9lAoUo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfxjXs%2FbtsL4EQmVKu%2FVkJkYvLClRh0aFO9lAoUo0%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;599&quot; height=&quot;131&quot; data-filename=&quot;스크린샷 2025-01-31 오후 6.30.43.png&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;131&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;- DNS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Load Balancing&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;왜 GSLB가 나오게 됐을까?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나름대로 이해한 내용을 정리해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;물리적인 거리의 한계&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유럽에서 살고 있는 사용자가 티스토리에 접속한다고 가정해보자. 사이트가 마법처럼 뿅하고 바로 접속되는 것이 아니니 어떤 과정을 거칠 것이다. 마침 티스토리의 데이터센터가 한국에만 있다고 해보자. 보통 우리가 네트워크 패킷을 주고 받았을 때의 과정을 공부했던 것을 간단하게 이야기하자면 사용자 컴퓨터에서 시작해 유럽의 어느 통신사 DNS에 도착할테고, 해당 DNS는 어떤 과정을 거쳐서 티스토리의 IP 주소를 알려줄 것이다. 이때 IP 주소는 티스토리의 데이터센터가 한국에만 있다고 가정했으니 한국의 IP 주소를 받을 것이다.&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;스크린샷 2025-01-28 오후 4.42.58.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rCPlq/btsL2QQLjI8/N0yQCKXtilhvx3nKBHalQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rCPlq/btsL2QQLjI8/N0yQCKXtilhvx3nKBHalQK/img.png&quot; data-alt=&quot;https://www.submarinecablemap.com/country/south-korea&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rCPlq/btsL2QQLjI8/N0yQCKXtilhvx3nKBHalQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrCPlq%2FbtsL2QQLjI8%2FN0yQCKXtilhvx3nKBHalQK%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;621&quot; height=&quot;364&quot; data-filename=&quot;스크린샷 2025-01-28 오후 4.42.58.png&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.submarinecablemap.com/country/south-korea&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;그러면 유럽에서 다시 티스토리 IP 주소로 패킷을 요청한다. 이때 해외에서 한국까지 네트워크 패킷을 전송하려면 보통 해저케이블을 사용한다. 위 사진처럼 한국에 많은 해저케이블이 깔려있는데, 유럽에서 요청한 네트워크 패킷은 유럽에서 시작해 한국에 도착하고, 통신사의 백본 네트워크에 가서 티스토리 서비스를 하는 데이터 센터로 이동한다. 이후 다시 응답을 할 때는 비슷한 과정을 반복할 것이다.&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;rarr; 한국, 한국 &amp;rarr; 유럽까지의 물리적 거리가 너무 멀다보니 느리게 패킷을 주고 받을 것이다. 특히 게임하는 사람들은 한국에서 유럽, 미국 게임 서버에 접속하면 핑이 굉장히 높은게 그런 이유다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;만약 서버에서 장애가 발생해 특정 IP 주소가 먹통인 상황&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-01-29 오전 11.24.06.png&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nESSF/btsL04Qzrf5/S2HyprUKg9JwMjsLsJl1D0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nESSF/btsL04Qzrf5/S2HyprUKg9JwMjsLsJl1D0/img.png&quot; data-alt=&quot;왼쪽, 가운데 (크롬), 오른쪽(터미널에서 dig naver.com 입력)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nESSF/btsL04Qzrf5/S2HyprUKg9JwMjsLsJl1D0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnESSF%2FbtsL04Qzrf5%2FS2HyprUKg9JwMjsLsJl1D0%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;1968&quot; height=&quot;256&quot; data-filename=&quot;스크린샷 2025-01-29 오전 11.24.06.png&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;왼쪽, 가운데 (크롬), 오른쪽(터미널에서 dig naver.com 입력)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;크롬에서 네이버를 입력 했을 때의 네트워크 헤더 정보를 확인해보면 이렇게 IP 주소가 살짝 다른 것을 볼 수 있다. 귀찮으면 터미널에서 `dig&lt;span&gt; &lt;/span&gt;&lt;/span&gt;naver.com`을 입력해보면 된다. 참고로 같은 URL로 dig 명령어를 실행하다보면 IP 주소의 순서가 달라지는걸 확인할 수 있다.&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;여기서 만약 223.130.200.xxx의 IP 주소 2개 모두 장애가 발생했다고 가정해보자. 사용자는 naver.com을 입력했더니 DNS는 223.130.200.xxx 주소를 제공할 때도 있을 것이고, 사용자 컴퓨터는 그 IP 주소로 패킷을 보냈더니 장애가 발생한 상황이라 패킷이 오지 않거나, 에러페이지가 나올 것이다. 이처럼 DNS는 장애가 발생했는지의 여부를 파악하지 못한채 IP 주소를  제공하므로 장애가 발생하면 사용자 만족도는 낮아질 수 밖에 없다.&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;총 정리하자면 GSLB가 나온 이유는 지리적인 이유 + DNS의 기술적 한계점를 보완해주는 기술이라고 보면 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;span&gt;&lt;b&gt;GSLB&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;GSLB의 역할&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.akamai.com/ko/glossary/what-is-global-server-load-balancing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Akamai&lt;/a&gt;, &lt;a href=&quot;https://www.cloudflare.com/ko-kr/learning/cdn/glossary/global-server-load-balancing-gslb/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cloud Flare&lt;/a&gt;, &lt;a href=&quot;https://kemptechnologies.com/global-server-load-balancing-gslb&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kemp Technologies&lt;/a&gt; 이런 기술 블로그 글을 확인해보니 아래와 같이 정리할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;전세계적으로 분포한 인터넷 트래픽을 적절한 데이터센터에 분산해 네트워크 부하를 줄이고, 고가용성을 제공해 안정적인 서비스를 제공하는 기술&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;DNS와 GSBL의 비교&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 링크에 궁금한 점이 잘 나와있고, 이걸 토대로 간단하게 정리한거라 제대로 볼 사람은 아래 링크를 통해 보는게 좋아보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.netmanias.com/ko/post/blog/5617/dns-data-center-gslb-kt-network-protocol/global-server-load-balancing-gslb-service-for-kt-ucloud&quot;&gt;KT 유클라우드, GSLB로 무중단 서비스 지원&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.netmanias.com/ko/post/blog/5620/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-1-concept-workflow&quot;&gt;Enterprise를 위한 GSLB 1편: 개념 및 서비스 로직&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.netmanias.com/ko/post/blog/5622/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-1&quot;&gt;Enterprise를 위한 GSLB 2편: Site/Server 선택 정책 (1)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.netmanias.com/ko/post/blog/5624/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-2&quot;&gt;Enterprise를 위한 GSLB 2편: Site/Server 선택 정책 (2)&lt;/a&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;Netmanias.2012.09.25-DNS_vs_GSLB.gif&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;824&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EncDR/btsL3rRV5RT/FdATepwCN23cnfKWA23lI0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EncDR/btsL3rRV5RT/FdATepwCN23cnfKWA23lI0/img.gif&quot; data-alt=&quot;https://www.netmanias.com/ko/post/blog/5620/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-1-concept-workflow&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EncDR/btsL3rRV5RT/FdATepwCN23cnfKWA23lI0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/EncDR/btsL3rRV5RT/FdATepwCN23cnfKWA23lI0/img.gif&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;760&quot; height=&quot;824&quot; data-filename=&quot;Netmanias.2012.09.25-DNS_vs_GSLB.gif&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;824&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.netmanias.com/ko/post/blog/5620/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-1-concept-workflow&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;DNS와 GSLB를 비교하면 위 사진으로 정리가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 재해 복구(DR): 헬스 체크를 통해 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;서버가 다운되더라도 다른 서버로 연결되게 한다. (DNS는 헬스 체크 없음)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;2. 사이트 부하 분산:&amp;nbsp; 트래픽이 몰리면 자동으로 트래픽이 없는 서버로 분배한다. (DNS는 트래픽 감지 없음)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;3. 네트워크 근접성: Local DNS와 SLB 사이의 RTT를 측정해 네트워크상으로 가까운 서버의 IP 주소를 알려준다. (DNS는 RTT 측정 없음)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;4. 지리적 근접성: 사용자의 지리적 위치에 가까운 서버의 IP 주소를 알려준다. (DNS는 지리적 위치를 고려하지 않음)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;KT GSLB의 동작 방식 (큰 흐름만)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Netmanias.2012.09.20-KT_ucloud_GSLB.gif&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gkl8m/btsL3OMZXL0/yPZyKm4nqWZshT7JEZ2kNK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gkl8m/btsL3OMZXL0/yPZyKm4nqWZshT7JEZ2kNK/img.gif&quot; data-alt=&quot;https://www.netmanias.com/ko/post/blog/5617/dns-data-center-gslb-kt-network-protocol/global-server-load-balancing-gslb-service-for-kt-ucloud&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gkl8m/btsL3OMZXL0/yPZyKm4nqWZshT7JEZ2kNK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/Gkl8m/btsL3OMZXL0/yPZyKm4nqWZshT7JEZ2kNK/img.gif&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;740&quot; height=&quot;503&quot; data-filename=&quot;Netmanias.2012.09.20-KT_ucloud_GSLB.gif&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.netmanias.com/ko/post/blog/5617/dns-data-center-gslb-kt-network-protocol/global-server-load-balancing-gslb-service-for-kt-ucloud&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;5를 제외한 1부터 8까지는 일반적인 DNS에 IP 주소를얻어 요청 패킷을 보내는 동작인데, 5번의 GSLB Policy에서 GSLB가 관여한다. 현재 구조는 active - backup(standby)이고, 여기에 나온 서버 1, 서버 2는 nginx와 같은 SLB(Server Load Balancing)이다. 만약 Server 2의 SLB가 관리하는 모든 서버가 터지면 2.2.2.2의 SLB는 active인 GSLB 1에게 보고해 DNS Query가 들어오면 자동적으로 1.1.1.1만 응답 패킷에 넣게 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;KT GSLB의 세부 동작 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Netmanias.2012.09.25-GSLB_Policy.gif&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbC1fN/btsL3y4AS9h/MQNy2Z6hKyMhf7k2U9PPpK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbC1fN/btsL3y4AS9h/MQNy2Z6hKyMhf7k2U9PPpK/img.gif&quot; data-alt=&quot;https://www.netmanias.com/ko/post/blog/5622/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbC1fN/btsL3y4AS9h/MQNy2Z6hKyMhf7k2U9PPpK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cbC1fN/btsL3y4AS9h/MQNy2Z6hKyMhf7k2U9PPpK/img.gif&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;550&quot; height=&quot;350&quot; data-filename=&quot;Netmanias.2012.09.25-GSLB_Policy.gif&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.netmanias.com/ko/post/blog/5622/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-1&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;GSLB가 특정 지역의 SLB IP 주소를 선택하는 것도 누군가가 결국은 코딩을 해야하니 위 방식으로 되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 큰 흐름을 잠깐 언급한 내용은 1번 과정의 Server Health 내용이다. 이후에는 아래 순서로 후보군들을 걸러 걸러 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 서버 상태 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 세션, 네트워크 부하가 적은 SLB 선택&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;4. 지리적 관점에서의 근접성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 현재 TCP, UDP 커넥션 연결이 적은 SLB를 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 운영자가 설정한 사이트 선호도(우선순위)로 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 트래픽 분배를 위해 덜 선택된 서버&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. Round Robin, Weighted Round Robin으로 서버 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 7, 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;더 자세한 내용이 궁금한 분은 &lt;a href=&quot;https://www.netmanias.com/ko/post/blog/5622/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;1편&lt;/a&gt;, &lt;a href=&quot;https://www.netmanias.com/ko/post/blog/5624/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2편&lt;/a&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;Netmanias.2012.09.28-GSLB_Comparision.gif&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MDn0h/btsL2430b1a/1sBHqIStTKsB4uEP7jD1c0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MDn0h/btsL2430b1a/1sBHqIStTKsB4uEP7jD1c0/img.gif&quot; data-alt=&quot;https://www.netmanias.com/ko/post/blog/5624/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MDn0h/btsL2430b1a/1sBHqIStTKsB4uEP7jD1c0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/MDn0h/btsL2430b1a/1sBHqIStTKsB4uEP7jD1c0/img.gif&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;740&quot; height=&quot;221&quot; data-filename=&quot;Netmanias.2012.09.28-GSLB_Comparision.gif&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.netmanias.com/ko/post/blog/5624/dns-data-center-gslb-network-protocol/global-server-load-balancing-for-enterprise-part-2-site-server-selection-policy-2&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;이 사진을 보니 KT는 SLB를 사용하는 것으로 보인다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;GSLB를 기반으로 어디서 활용할 수 있을까?&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 D2 기술블로그에 간단하게 GCDN(Global Content Delivery Network)이라는 기술도 사용한다고 나와있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;a href=&quot;https://d2.naver.com/helloworld/6070967&quot;&gt;https://d2.naver.com/helloworld/6070967&lt;/a&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;보통 CDN이라하면 보통 잘 바뀌지 않는 html, css, js, 이미지 파일등을 전송하는데, 여기서도 GSLB 기술을 사용하여 가장 가까운 CDN 서버로 전송하는 것이다. 이러면 결국 GSLB처럼 먼 해외에 사는 사용자는 서비스중인 해외 데이터센터에서 파일을 가져와 한국 데이터센터에서 네트워크 통신하는 것보다 더 빠른 속도를 체감할 수 있다.&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;이런 목적으로 사용한다고 생각해보니 글로벌 서비스를 운영한다면 여러 데이터센터에서 서버가 구동될테니 CDN 서버처럼 일반 서버와 다른 자체 서버를 가지고 있다면 비슷하게 사용하지 않을까 생각한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이외에 읽으면 좋은 링크&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://zdnet.co.kr/view/?no=00000010055390&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ZDNET: 효율적인 부하 분산 라우팅을 위한 GSLB 기술 활용&lt;/a&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;취준할 때는 큰 흐름의 패킷 이동과 관련해 간단하게만 공부 한 내용인데, 제대로 공부해보니 &quot;왜 GSLB가 나오게 됐을까?&quot;라는 의문에 대한 자료가 잘 만들어져 있어서 공부하기 편했다.&lt;/p&gt;</description>
      <category>공부/컴퓨터 네트워크</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/610</guid>
      <comments>https://hello70825.tistory.com/610#entry610comment</comments>
      <pubDate>Fri, 31 Jan 2025 23:03:30 +0900</pubDate>
    </item>
    <item>
      <title>[OS, Java] Zero Copy</title>
      <link>https://hello70825.tistory.com/604</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-31 오전 8.47.46.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;131&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ljd2F/btsIS7ARWg1/gi62MWms7ijs1Io7JB8B3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ljd2F/btsIS7ARWg1/gi62MWms7ijs1Io7JB8B3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ljd2F/btsIS7ARWg1/gi62MWms7ijs1Io7JB8B3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fljd2F%2FbtsIS7ARWg1%2Fgi62MWms7ijs1Io7JB8B3k%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;424&quot; height=&quot;131&quot; data-filename=&quot;스크린샷 2024-07-31 오전 8.47.46.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;131&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;올해 4월달쯤에 간단하게 공부하다가 넘어간 것 같은데, 이번에 제대로 공부할 기회가 생겼다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zero Copy는 CPU를 사용하지 않고, 디스크/메모리에 저장된 정보를 다른 메모리에 저장하는 방식으로 기존 전통적인 데이터 복사 방식보다 더 성능이 좋은 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 이번 내용은 운영체제 이론, 소켓에 대해 알고 있어야한다. (&lt;a href=&quot;https://hello70825.tistory.com/598&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;소켓 관련 글&lt;/a&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. Zero Copy 이전에 사용하는 방법&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2CpBR/btsIQytqtGd/OFjO3WbOsFfLHqVKBGD440/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2CpBR/btsIQytqtGd/OFjO3WbOsFfLHqVKBGD440/img.png&quot; data-alt=&quot;https://www.redhat.com/en/blog/architecting-containers-part-1-why-understanding-user-space-vs-kernel-space-matters&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2CpBR/btsIQytqtGd/OFjO3WbOsFfLHqVKBGD440/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2CpBR%2FbtsIQytqtGd%2FOFjO3WbOsFfLHqVKBGD440%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;588&quot; height=&quot;232&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.redhat.com/en/blog/architecting-containers-part-1-why-understanding-user-space-vs-kernel-space-matters&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;운영체제에서 사용자 - 커널 공간이 따로 나뉘어져 있는 그림을 많이 봤을 것이다. 코드를 동작할 때, 동작 원리를 깊숙히 들어가면 system call이 호출되는 형식이다. 데이터 복사도 마찬가지로 system call을 사용해서 유저 영역과 커널 영역을 넘나들게 된다.&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;데이터 복사에서 제일 많이 사용하는 곳은 여러가지가 있겠지만 대표적으로 소켓 통신이 있다. API 통신은 소켓을 통해 패킷을 송수신하게 되고, 데이터베이스도 연결한다면 데이터베이스의 SELECT, UPDATE, DELETE 등과 같은 명령어들도 소켓을 통해 작업이 이루어진다. 이때의 과정이 소켓에 있는 데이터를 buffer에 가져오게 되므로 데이터를 복사하게 된다. 왜냐하면 TCP / UDP와 같은 Transport Layer 영역부터는 커널이 관리하는 영역이기 때문이다.&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;만약 서버가 API 통신을 가정하고, 클라이언트에게 API 요청에 대한 응답을 보낸다고 가정하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 응답값은 텍스트 파일에 있는 정보를 가져온다고 해보자&lt;/p&gt;
&lt;pre id=&quot;code_1722403047032&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);&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;위 코드는 File.read(...)를 통해 디스크에 저장된 텍스트 파일을 읽고, Socket.send(...)로 값을 보내는 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;368&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/005EX/btsITiWHFSP/zfqu6pOfFP35NzyZWpu2ck/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/005EX/btsITiWHFSP/zfqu6pOfFP35NzyZWpu2ck/img.gif&quot; data-alt=&quot;https://developer.ibm.com/articles/j-zerocopy/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/005EX/btsITiWHFSP/zfqu6pOfFP35NzyZWpu2ck/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/005EX/btsITiWHFSP/zfqu6pOfFP35NzyZWpu2ck/img.gif&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;420&quot; height=&quot;368&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;368&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://developer.ibm.com/articles/j-zerocopy/&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;* DMA copy는 Direct Memory Access로 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;[1] read() 호출시 디스크에 저장된 값을 DMA를 통해 메모리의 Read buffer에 복사한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2] Read buffer는 커널에 있으므로 사용자가 접근하지 못하기 때문에 Application buffer로 복사한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3] send() 호출시 소켓을 통해 데이터를 보내야하므로 Application buffer 데이터를 Socket buffer로 복사한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[4] 패킷을 네트워크로 보내려면 NIC를 통해야하므로 NIC buffer로 복사한다. (NIC : Network Interface Card)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 데이터가 4번 복사된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvkDct/btsISK0vVF9/ib1DblX9pSASHWkMFy6QWk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvkDct/btsISK0vVF9/ib1DblX9pSASHWkMFy6QWk/img.gif&quot; data-alt=&quot;https://developer.ibm.com/articles/j-zerocopy/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvkDct/btsISK0vVF9/ib1DblX9pSASHWkMFy6QWk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dvkDct/btsISK0vVF9/ib1DblX9pSASHWkMFy6QWk/img.gif&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;405&quot; height=&quot;310&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://developer.ibm.com/articles/j-zerocopy/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 성능 문제는 이 컨텍스트 스위칭에서 발생하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[1 - 유저 &amp;rarr; 커널] read() 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2 - 커널 &amp;rarr; 유저] 디스크에 있는 데이터를 DMA를 통해 Read buffer에 복사 후, Application buffer에 복사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[3 - 유저 &amp;rarr; 커널] send() 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[4 - 커널 &amp;rarr; 유저] Application buffer &amp;rarr; Socket buffer &amp;rarr; NIC buffer로 복사 후 컨텍스트 스위칭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 보면 명령어가 2개라서 최적화를 못한건가 생각이 들었는데, 여기에서도 각각 장점이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째로 Read buffer가 일종의 Readahead Cache 기능을 한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 무슨 말일까?? 예를 들어서 Read buffer가 4KB라고 하고, read()에서 1KB만 읽는다고 할 때, 일단 디스크에 4KB 데이터를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Read buffer에 &lt;/span&gt;복사한다. 이후 read()가 이후 추가적인 1KB를 요청한다면 Read buffer에 이미 데이터가 존재하기 때문에 캐시처럼 동작하게 된다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;두 번째로 &lt;/span&gt;Socket buffer는 비동기 처리가 가능하다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;만약 Application buffer &amp;rarr; NIC buffer로 간다고 하면 사용자 입장에서는 블로킹 상태가 된다. 하지만 비동기 처리가 가능하게 된다면 Application buffer &amp;rarr; Socket buffer로 복사하기만 해도 완료되었다고 처리할 수 있다. 이후엔 커널이 알아서 비동기로 처리하면 되는 것이다. 잘 와닿지 않는다면 NIC buffer 대신 시간이 오래 걸리는 디스크에 저장한다고 생각해보자. 유저 &amp;rarr; 디스크로 다이렉트로 저장하게된다면 디스크에 파일이 저장될 때까지 기다려야하는 블로킹이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만... 이것도 결국 한계점은 있었다&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;Readahead Cache의 전제 조건은 (Read Buffer 크기) &amp;gt; (&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;사용자 요청 데이터)일 때&lt;/span&gt;&amp;nbsp;얻을 수 있는 장점이라는 것이다. 하지만 요즘 데이터는 한 번의 요청에 Read buffer 한 번으로도 충분하지 않은 경우가 있기 때문에 성능 병목이 발생해버렸다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. Zero Copy&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[1] 불완전한 제로 카피&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1722417514238&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);&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;제로 카피는 어디를 개선할 수 있을까?? 생각해보면 우리가 작성하는 코드는 위와 같이 File.read(...), Socket.send(...)로 서로 연속된 코드를 작성하고 있다. 최적화한다면 read()와 send()를 하나로 합칠 수도 있다는 점이다.&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;스크린샷 2024-07-31 오후 6.21.00.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc1Xc9/btsIQeIX92f/XhcE32L5MXMSKBABd2v1zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc1Xc9/btsIQeIX92f/XhcE32L5MXMSKBABd2v1zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc1Xc9/btsIQeIX92f/XhcE32L5MXMSKBABd2v1zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc1Xc9%2FbtsIQeIX92f%2FXhcE32L5MXMSKBABd2v1zk%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;380&quot; height=&quot;329&quot; data-filename=&quot;스크린샷 2024-07-31 오후 6.21.00.png&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 하나로 합친다면 파란 네모박스의 2, 3 과정이 없어진다. 이 말은 중간 과정에 발생하는 두 번의 컨텍스트 스위치가 사라지게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722417825709&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;sys/socket.h&amp;gt;
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

참고 링크: https://man7.org/linux/man-pages/man2/sendfile.2.html&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;Linux에서는 sendfile 이라는 것을 지원해준다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1722417972860&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract long transferTo(long position, long count, WritableByteChannel target);
public abstract long transferFrom(ReadableByteChannel src, long position, long count);&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;자바의 NIO에서는 transferTo(), transferFrom()을 지원해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vemRF/btsIQLTWVcL/wwAHmj1bd32cz58dnRgnrK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vemRF/btsIQLTWVcL/wwAHmj1bd32cz58dnRgnrK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vemRF/btsIQLTWVcL/wwAHmj1bd32cz58dnRgnrK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/vemRF/btsIQLTWVcL/wwAHmj1bd32cz58dnRgnrK/img.gif&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;350&quot; height=&quot;312&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m7E3E/btsISsskHda/4TI8EjpM2XQSA2Ai4bFu31/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m7E3E/btsISsskHda/4TI8EjpM2XQSA2Ai4bFu31/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m7E3E/btsISsskHda/4TI8EjpM2XQSA2Ai4bFu31/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/m7E3E/btsISsskHda/4TI8EjpM2XQSA2Ai4bFu31/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;174&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;174&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;rarr; Read buffer &amp;rarr; Socket buffer &amp;rarr; NIC buffer로 동작하게 된다. 데이터 복사는 4번 &amp;rarr; 3번으로 줄어들고, 복사 과정에서 CPU 연산은 2회 &amp;rarr; 1회로 사용된다. 거기다가 컨텍스트 스위치는 유저 &amp;rarr; 커널 &amp;rarr; 유저로 두 번만 일어나게 된다.&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;게다가 제로 카피라는 말은 CPU를 전혀 사용하지 않고 복사를 하는 방법이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[2] 완전한 제로 카피&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-31 오후 6.43.33.png&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnK8b5/btsIReImix5/FE9W8Bh622R7qOP4HUKBoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnK8b5/btsIReImix5/FE9W8Bh622R7qOP4HUKBoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnK8b5/btsIReImix5/FE9W8Bh622R7qOP4HUKBoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnK8b5%2FbtsIReImix5%2FFE9W8Bh622R7qOP4HUKBoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;388&quot; height=&quot;340&quot; data-filename=&quot;스크린샷 2024-07-31 오후 6.43.33.png&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 sendfile(...), transferTo(...), transferFrom(...)을 사용하는 것은 그대로인데, 내부 동작 과정이 바뀌게 되어 제로 카피가 완성되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v92OG/btsIUvB4H3V/YcFHzyJ3ske2GKclnqW99k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v92OG/btsIUvB4H3V/YcFHzyJ3ske2GKclnqW99k/img.png&quot; data-alt=&quot;https://www.micahlerner.com/2021/07/07/breakfast-of-champions-towards-zero-copy-serialization-with-nic-scatter-gather.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v92OG/btsIUvB4H3V/YcFHzyJ3ske2GKclnqW99k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv92OG%2FbtsIUvB4H3V%2FYcFHzyJ3ske2GKclnqW99k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;142&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.micahlerner.com/2021/07/07/breakfast-of-champions-towards-zero-copy-serialization-with-nic-scatter-gather.html&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;IBM 문서에서 NIC가 gather 연산을 지원하게 되어 내부 동작이 바뀌었다는데, gather 연산이 어떤 역할인지 찾아보니 정확한 이름은 scatter-gather로 분산 수집이라는 뜻을 가지고 있다. 분산 수집 기능이 없었을 때는 이전까지 분산된 데이터를 Socket buffer라는 곳에 하나로 모아서 NIC buffer로 보내야 했다. 간단하게 이야기하면 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;연속된 메모리 주소를 가져야 DMA copy를 할 수 있었다는 점이다.&lt;/span&gt; 하지만 기술 발전에 따라 scatter-gather가 나오게 됐고, 이후 하드웨어 발달로 인해 NIC 카드가 scatter-gather 연산을 지원하게 되어 비연속적인 주소에 저장된 데이터들을 NIC가 처리할 수 있게 되었다. (scatter-gather에 대한 자세한 내용은 맨 아래 참고한 링크 확인)&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;이것을 통해 위 사진의 파란 박스도 사라지게 되어 CPU는 데이터 복사에서 해방됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bApYxU/btsIRVIjc2K/M4XHTXwCPXQwXGHMPIpuc0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bApYxU/btsIRVIjc2K/M4XHTXwCPXQwXGHMPIpuc0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bApYxU/btsIRVIjc2K/M4XHTXwCPXQwXGHMPIpuc0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bApYxU/btsIRVIjc2K/M4XHTXwCPXQwXGHMPIpuc0/img.gif&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;350&quot; height=&quot;352&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;352&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;대신 디스크립터가 새로 생겼는데, Socket buffer에 데이터를 직접적으로 복사하는 것이 아닌 Descriptor를 통해 어느 곳에 어느 크기의 데이터가 있는지 간접적으로 확인할 수 있게 된다. NIC buffer에 scatter-gather 방식으로 데이터를 보내줄 수 있게 됐고, CPU가 데이터 복사에서 할 일이 없어지게 됐다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[3] 성능 비교&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-31 오후 6.59.48.png&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mo5G9/btsIRUWUVQR/nXC27Eo9y56gI7W74kiTlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mo5G9/btsIRUWUVQR/nXC27Eo9y56gI7W74kiTlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mo5G9/btsIRUWUVQR/nXC27Eo9y56gI7W74kiTlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmo5G9%2FbtsIRUWUVQR%2FnXC27Eo9y56gI7W74kiTlK%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;751&quot; height=&quot;430&quot; data-filename=&quot;스크린샷 2024-07-31 오후 6.59.48.png&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;430&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 두 배 이상 차이난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 Apache Kafka에 제로 카피가 적용되어 있어서 카프카를 사용하는 많은 이유중에 하나라고 한다. 이와 반대로 Apache Kafka 다음으로 많이 쓰이는 RabbitMQ는 안정성을 중시하기 때문에 제로 카피는 사용하지 않는다고 한다. Apache Pulsar는 깃허브 PR을 찾아보니 제로 카피를 일부 지원하고 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;참고한 링크&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글은 1번 내용을 기반으로 작성했다. 부족한 부분은 2번 ~ 5번 내용을 참조했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DMA copy에 대해 더 궁금하신 분은 4번, 5번을 읽어보는걸 추천하고, 자바 NIO에 대해 더 궁금하신 분은 6번을 읽어보는걸 추천한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;a href=&quot;https://developer.ibm.com/articles/j-zerocopy/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IBM Developer - Efficient data transfer through zero copy&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;a href=&quot;https://www.kernel.org/doc/html/v4.18/networking/msg_zerocopy.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Linux Kernel Documentation - MSG_ZEROCOPY&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;a href=&quot;https://lwn.net/Articles/726917/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;LWN net - Zero-copy networking&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;a href=&quot;https://yohda.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%BB%A4%EB%84%90-DMA-overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;yohda 블로그 - [리눅스 커널] DMA - overview&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &lt;a href=&quot;https://lwn.net/Articles/234617/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;LWN net - Scatterlist chaining&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. &lt;a href=&quot;https://mark-kim.blog/understanding-non-blocking-io-and-nio/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mark Kim 블로그 - 사례를 통해 이해하는 네트워크 논블로킹 I/O와 Java NIO&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/Java</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/604</guid>
      <comments>https://hello70825.tistory.com/604#entry604comment</comments>
      <pubDate>Wed, 31 Jul 2024 19:15:59 +0900</pubDate>
    </item>
    <item>
      <title>[Java] ReentrantLock</title>
      <link>https://hello70825.tistory.com/603</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6keFR/btsIGs1pq5Q/43S43Zr5J6XygY0LkvnM9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6keFR/btsIGs1pq5Q/43S43Zr5J6XygY0LkvnM9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6keFR/btsIGs1pq5Q/43S43Zr5J6XygY0LkvnM9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6keFR%2FbtsIGs1pq5Q%2F43S43Zr5J6XygY0LkvnM9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;205&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 주 전에 가상 스레드를 공부하기로 했는데, 생각보다 공부할게 너무 많아서 잘못 건드렸다는 생각이 많이 든다. 포스팅을 적어도 2주에 한 번씩은 하자고 생각했는데, 2주는 무슨 거의 한 달이 된 상황... 그래서 야금야금 분할정복하듯이 키워드를 적어보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 운영체제에 있는 내용은 안다고 가정하고 글을 작성함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* CAS 알고리즘에 대해 알고 있으면 좋다 (&lt;a href=&quot;https://hello70825.tistory.com/592&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CAS 알고리즘 포스팅 글&lt;/a&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. &lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Synchornized&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 락은 &lt;b&gt;모니터&lt;/b&gt; 개념을 사용하고 있다. 모니터란 특정 순간에 하나의 스레드만 객체 인스턴스에 접근할 수 있는 뮤텍스라고 생각하면 된다. 예를 들어서 메서드에 synchronized를 적용하면 인스턴스 메서드에 락이 걸리고, synchronized(객체 인스턴스)를 적용하면 객체 인스턴스에 락이 걸린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQTuez/btsIG9s9SIN/3BK5pFSOmVhloY3M6hucf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQTuez/btsIG9s9SIN/3BK5pFSOmVhloY3M6hucf1/img.png&quot; data-alt=&quot;HashTable&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQTuez/btsIG9s9SIN/3BK5pFSOmVhloY3M6hucf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQTuez%2FbtsIG9s9SIN%2F3BK5pFSOmVhloY3M6hucf1%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;507&quot; height=&quot;388&quot; data-origin-width=&quot;638&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HashTable&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-20 오후 9.53.39.png&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;333&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bucs9V/btsIGqWO4n5/qgopSQYeWhqFry8mgK5Bvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bucs9V/btsIGqWO4n5/qgopSQYeWhqFry8mgK5Bvk/img.png&quot; data-alt=&quot;ConcurrentHashMap&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bucs9V/btsIGqWO4n5/qgopSQYeWhqFry8mgK5Bvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbucs9V%2FbtsIGqWO4n5%2FqgopSQYeWhqFry8mgK5Bvk%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;472&quot; height=&quot;333&quot; data-filename=&quot;스크린샷 2024-07-20 오후 9.53.39.png&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;333&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ConcurrentHashMap&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;synchronized는 사용 방법은 HashTable, ConcurrentHashMap을 대표 스샷으로 가지고 왔다. 위 사진처럼 객체나 메서드에 synchronized를 적용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여담으로 ConcurrentHashMap은 이런 락의 범위를 최소화 시켜서 성능상의 이점을 노렸다.&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-origin-width=&quot;589&quot; data-origin-height=&quot;555&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BcyMe/btsIGZxEpC6/K2gIjGczVkvXkfRLKWMJZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BcyMe/btsIGZxEpC6/K2gIjGczVkvXkfRLKWMJZ0/img.png&quot; data-alt=&quot;https://github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/objectMonitor.cpp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BcyMe/btsIGZxEpC6/K2gIjGczVkvXkfRLKWMJZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBcyMe%2FbtsIGZxEpC6%2FK2gIjGczVkvXkfRLKWMJZ0%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;589&quot; height=&quot;555&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;555&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/objectMonitor.cpp&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;그러면 모니터는 구체적으로 어떻게 동작할까?? JVM의 objectMonitor 코드를 보면 주석에 이런 저런 내용이 담겨있는데, 주요 내용을 정리하면 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 임계구역에 진입하기 위한 스레드 경쟁은 CAS (Compare and Swap) 알고리즘을 사용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CAS 알고리즘을 사용하면 뒤따라오는 문제점인 ABA 문제는 해결했다.&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;정리하면 락을 얻기 위한 스레드간 경쟁은 CAS 알고리즘을 사용했고, 실제 락은 뮤텍스 락으로 구현 했다는 점이다.&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;참고로 락도 정보를 가지고 있는데, 객체에 접근하는 스레드의 개수가 몇개냐에 따라 Biased Lock &amp;rarr; LightWeightLock &amp;rarr; HeavyWeightLock 순서로 업그레이드를 하며 변하게 된다. 여기에 대해 궁금한 분들은 &lt;a href=&quot;https://www.alibabacloud.com/blog/lets-talk-about-several-of-the-jvm-level-locks-in-java_596090?source=post_page-----84e78b76767b--------------------------------&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Alibaba Cloud Blog - Let's Talk about Serveral of the JVM-level Locks in Java&lt;/a&gt;&amp;nbsp;글을 참고하면 좋다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. Synchronized의 한계&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 1.4까지는 syncrhonized 키워드로만 Thread-Safe하게 만들 수 있었는데, 1.5부터 java.util.concurrent 패키지가 추가되어 개발자가 동시성 제어를 쉽게 할 수 있도록 만들었다. 이외엔 제네릭, enum도 추가된 버전이다.&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;이중에서 java.util.concurrent.locks이 나오게 된 계기는 synchronized 만으로는 동시성을 충분히 제어할 수 없기 때문이다. 운영체제 시간에 Lock에 대해 다룬다면 wait()과 notify()에 대해 들어봤을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[락 획득 순서가 보장되지 않음]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;톰캣에 스레드 풀이 있는 것처럼 자바 객체 인스턴스마다 고유의 대기 풀(Waiting Pool)이 존재한다. 객체마다 가지고 있는건데, wait() 메서드를 호출하면 해당 스레드는 대기 풀에 들어가게 된다. 이후 다시 락을 획득시키기 위해서 notify()를 호출할텐데, 여기서의 문제점은 어느 객체를 깨우는지 명시를 안해두고 있다. 대기 풀에 있는 랜덤한 스레드 1개가 락을 획득한다는 것이다. 이건 기아상태가 발생할 수도 있다는 것을 시사한다. 이렇게 오래 기다린 순으로 스레드가 락을 획득하지 못하는 것을 Unfair Lock이라고도 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[경쟁 조건에 대한 성능 저하]&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;notify() 대신 스레드를 깨우는 다른 방법은 notifyAll()이다. 대기 풀에 있는 모든 스레드를 깨운다는 것인데, 내가 원하는 대기 풀의 스레드를 깨우는 것이 아니라서 락을 획득하기 위한 경쟁을 하게 된다. 즉 내가 경쟁 조건을 세밀하게 제어할 수 없다는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Coffee coffee = new Coffee();&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Machine machine = new Machine(coffee);&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Barista barista = new Barista(coffee);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Customer customer1 = new Customer(coffee);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Customer customer2 = new Customer(coffee);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Customer customer3 = new Customer(coffee);&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;예를 들어서 위와 같은 코드가 있다고 가정하자. 이때 기계, 바리스타와 소비자 모두 Coffee에 synchronized가 적용된 메서드를 호출한 상황이다. 만약 기계가 먼저 락을 획득 했다면 Coffee의 대기 풀엔&amp;nbsp; {barista, customer1, customer2, customer3}가 들어간 상태이다. 이후 커피가 완성되어서 바리스타만 깨우고 싶은 상황이 존재하는데, customer 1 ~ 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;정리하면 synchornized 단점은 크게 2가지로 나눌 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 대기 풀에 들어간 스레드를 랜덤으로 1개 깨우거나, 모두 깨워서 경쟁 상태를 만든다 ( = Unfair Lock)&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;그래서 이런 한계점을 개선한 것이 ReentrantLock이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. ReentrantLock&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reentrant 단어는 재진입성이라는 뜻을 가지고 있다. 언제든지 락을 걸고 해제할 수 있다는 뜻으로 실제 lock(), unlock() 메서드를 사용하여 명시적으로 락을 관리한다. 그런 의미에서 synchronized는 암묵적 락이라고도 부른다.&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;스크린샷 2024-07-21 오전 9.01.05.png&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;461&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cN8AYx/btsIIH98MG7/NNAQ7lRfvI0ykM38JeioU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cN8AYx/btsIIH98MG7/NNAQ7lRfvI0ykM38JeioU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cN8AYx/btsIIH98MG7/NNAQ7lRfvI0ykM38JeioU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcN8AYx%2FbtsIIH98MG7%2FNNAQ7lRfvI0ykM38JeioU1%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;665&quot; height=&quot;461&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.01.05.png&quot; data-origin-width=&quot;665&quot; data-origin-height=&quot;461&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;java.util.concurrent.locks가 추가되면서 Lock 인터페이스가 추가 됐는데, Lock의 기본 구현체가 ReentrantLock이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[락 획득 순서를 보장할 수 있음]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-21 오전 8.58.12.png&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuWR5k/btsIIxT3Vw9/H2NJnmuDmNJv6yUW5Rm280/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuWR5k/btsIIxT3Vw9/H2NJnmuDmNJv6yUW5Rm280/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuWR5k/btsIIxT3Vw9/H2NJnmuDmNJv6yUW5Rm280/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuWR5k%2FbtsIIxT3Vw9%2FH2NJnmuDmNJv6yUW5Rm280%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;590&quot; height=&quot;259&quot; data-filename=&quot;스크린샷 2024-07-21 오전 8.58.12.png&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;259&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;ReentrantLock은 Unfair Lock, Fair Lock 모두 지원을 해주는데, Fair Lock은 가장 오래 기다린 스레드가 먼저 락을 획득하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[Condition을 활용한 원하는 경쟁조건에 따른 성능 개선]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;synchronized와 다르게 ReentrantLock은 대기 풀을 구분할 수 있다. Condition을 사용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Coffee coffee = new Coffee();&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Machine machine = new Machine();&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Barista barista = new Barista(coffee);&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Customer customer1 = new Customer(coffee);&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Customer customer2 = new Customer(coffee);&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Customer customer3 = new Customer(coffee);&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드가 있으면&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ReentrantLock lock = new ReentrantLock();&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Condition waitMachine = lock.newCondition();&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Condition waitBarista = lock.newCondition();&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Condition waitCustomer = lock.newCondition();&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;으로 대기 풀을 각자 다르게 설정할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이후 wait() 대신 await(), notify() 대신 signal()을 사용해서 대기 풀을 넣을 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;[대기 큐]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.11.02.png&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXahcD/btsIHADZR5P/yUUMuxoRulj0YF8W2aYThK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXahcD/btsIHADZR5P/yUUMuxoRulj0YF8W2aYThK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXahcD/btsIHADZR5P/yUUMuxoRulj0YF8W2aYThK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXahcD%2FbtsIHADZR5P%2FyUUMuxoRulj0YF8W2aYThK%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;404&quot; height=&quot;76&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.11.02.png&quot; data-origin-width=&quot;404&quot; data-origin-height=&quot;76&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;ReentrantLock의 대기 큐는 AbstractQueueSynchronizer (AQS)를 기반으로 구현되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-07-21 오후 7.26.15.png&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r6jfI/btsIIhYlYTU/ggSB6h3kyWZhMmocGknKDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r6jfI/btsIIhYlYTU/ggSB6h3kyWZhMmocGknKDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r6jfI/btsIIhYlYTU/ggSB6h3kyWZhMmocGknKDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr6jfI%2FbtsIIhYlYTU%2FggSB6h3kyWZhMmocGknKDk%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;489&quot; height=&quot;117&quot; data-filename=&quot;스크린샷 2024-07-21 오후 7.26.15.png&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;117&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;여기서 AQS는 volatile과 CAS 알고리즘을 기반으로 만들어졌는데, 스핀락에서 사용하는 CLH 큐의 변형이라고 한다. (CLH = Craig, Landin, and Hagersten)&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;스크린샷 2024-07-21 오전 9.22.33.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/03ge5/btsIHGEbN4w/ZI9OQGJosG9Vc3baRCkHp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/03ge5/btsIHGEbN4w/ZI9OQGJosG9Vc3baRCkHp0/img.png&quot; data-alt=&quot;엥 대기큐라며..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/03ge5/btsIHGEbN4w/ZI9OQGJosG9Vc3baRCkHp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F03ge5%2FbtsIHGEbN4w%2FZI9OQGJosG9Vc3baRCkHp0%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;635&quot; height=&quot;163&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.22.33.png&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;엥 대기큐라며..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 코드를 확인해보면 실제 노드는 큐가 아닌 더블링크드리스트로 이루어져 있다.&lt;/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;스크린샷 2024-07-21 오전 9.16.13.png&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1Y1ky/btsIHXr9Z6a/XWOOKhZHXPkJYQsSPpolhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1Y1ky/btsIHXr9Z6a/XWOOKhZHXPkJYQsSPpolhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1Y1ky/btsIHXr9Z6a/XWOOKhZHXPkJYQsSPpolhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1Y1ky%2FbtsIHXr9Z6a%2FXWOOKhZHXPkJYQsSPpolhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;233&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.16.13.png&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 코드를 뜯어보면 멤버 변수는 volatile을 키워드가 선언되어 있고&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;스크린샷 2024-07-21 오전 9.17.15.png&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL9vll/btsIHy0vdSz/QITQBMkkMVx8uJmdK3BoRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL9vll/btsIHy0vdSz/QITQBMkkMVx8uJmdK3BoRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL9vll/btsIHy0vdSz/QITQBMkkMVx8uJmdK3BoRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL9vll%2FbtsIHy0vdSz%2FQITQBMkkMVx8uJmdK3BoRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;585&quot; height=&quot;454&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.17.15.png&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;454&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐 삽입의 경우 CAS 알고리즘이 적용되어 있고&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;스크린샷 2024-07-21 오전 9.18.10.png&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxzDX2/btsIGa7KVMu/a4Ur7AvTzClMM3HrgNnf61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxzDX2/btsIGa7KVMu/a4Ur7AvTzClMM3HrgNnf61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxzDX2/btsIGa7KVMu/a4Ur7AvTzClMM3HrgNnf61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxzDX2%2FbtsIGa7KVMu%2Fa4Ur7AvTzClMM3HrgNnf61%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;566&quot; height=&quot;249&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.18.10.png&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;249&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대기 큐에서 락을 획득하는건 스핀락을 부분적으로 사용하고 있다. 스핀락은 이론적으로만 배웠는데, 실제 사용하는 곳은 처음본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQFjYO/btsIGiYYjRk/r56Nens4wnnkBs8kjDpnZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQFjYO/btsIGiYYjRk/r56Nens4wnnkBs8kjDpnZK/img.png&quot; data-alt=&quot;https://www.alibabacloud.com/blog/lets-talk-about-several-of-the-jvm-level-locks-in-java_596090?source=post_page-----84e78b76767b--------------------------------&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQFjYO/btsIGiYYjRk/r56Nens4wnnkBs8kjDpnZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQFjYO%2FbtsIGiYYjRk%2Fr56Nens4wnnkBs8kjDpnZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;417&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.alibabacloud.com/blog/lets-talk-about-several-of-the-jvm-level-locks-in-java_596090?source=post_page-----84e78b76767b--------------------------------&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 위 그림이 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. ReentrantLock이 다시 언급되고 있는 이유&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&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;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl9YCN/btsIG2Ov7BT/FREJp0oOwp1iVxeUvWRNX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl9YCN/btsIG2Ov7BT/FREJp0oOwp1iVxeUvWRNX1/img.png&quot; data-alt=&quot;https://techblog.woowahan.com/15398/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl9YCN/btsIG2Ov7BT/FREJp0oOwp1iVxeUvWRNX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl9YCN%2FbtsIG2Ov7BT%2FFREJp0oOwp1iVxeUvWRNX1%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;541&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://techblog.woowahan.com/15398/&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;자바의 경량 스레드인 가상 스레드 때문이다. 경량 스레드가 나오게 된 이유는 CPU 자원을 효율적으로 활용하는 것처럼 이제는 스레드 자원도 효율적으로 사용하는 방식으로 생각하면 편하다. 기존 자바의 스레드 방식은 [커널 스레드 - 유저 스레드]가 한 쌍으로 1대1 매핑이 되어있는데, 경량 스레드로 인해 N:M 관계가 되었다. 그래서 경량 스레드로 좋은 성능이 나오려면 경량 스레드가 블로킹이 일어날 때, 블로킹된 경량 스레드와 연결된 커널 스레드는 연결을 끊고, 새로운 경량 스레드랑 연결하여 작업해야한다.&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;하지만 Pinning 현상이라는 것이 있는데, 경량 스레드가 블로킹 상태가 되면 커널 스레드와 연결이 끊겨야 하는데, 계속 연결이 유지되고 있는 현상이다. 이것은 곧 커널 스레드도 블로킹 상태가 되기 때문에 기존 자바 Thread 방식과 똑같아진다. 이게 synchornized를 사용하게 된다면 Pinning 현상이 일어나기 때문에&amp;nbsp;synchornized에서 ReentrantLock으로 점차 변경할 예정이라고 한다.&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;스크린샷 2024-07-21 오전 9.31.15.png&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qSnn2/btsIHJU9ztb/KanYFpFT7vjUmx3xTO2aDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qSnn2/btsIHJU9ztb/KanYFpFT7vjUmx3xTO2aDk/img.png&quot; data-alt=&quot;https://openjdk.org/jeps/444&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qSnn2/btsIHJU9ztb/KanYFpFT7vjUmx3xTO2aDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqSnn2%2FbtsIHJU9ztb%2FKanYFpFT7vjUmx3xTO2aDk%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;538&quot; height=&quot;92&quot; data-filename=&quot;스크린샷 2024-07-21 오전 9.31.15.png&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://openjdk.org/jeps/444&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서는 이런 내용도 있고, 스프링에서는 synchornized와 관련해서 가상 스레드에 대한 내용도 있으니 참고해보면 좋을 것 같다. (&lt;a href=&quot;https://spring.io/blog/2022/10/11/embracing-virtual-threads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;관련 링크&lt;/a&gt;) 스프링에서는 이미 synchronized 블록을 옛날부터 수정해와서 좋은 상태를 유지하고 있지만, 가상 스레드를 최대한 활용할 수 있도록 검토한다고 나와있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;5. 참고한 링크&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) &lt;a href=&quot;https://www.alibabacloud.com/blog/lets-talk-about-several-of-the-jvm-level-locks-in-java_596090?source=post_page-----84e78b76767b--------------------------------&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Alibaba Cloud Blog -&amp;nbsp; Let's Talk about Several of the JVM-level Locks in Java&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) &lt;a href=&quot;https://github.com/wjdrbs96/Today-I-Learn/blob/master/Java/Thread/java.util.concurrent.locks/ReentrantLock%EC%9D%B4%EB%9E%80%3F.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;wjdrbs96님 깃허브 - TIL - ReentrantLock이란?&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) &lt;a href=&quot;https://techblog.woowahan.com/15398/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;우아한형제들 기술 블로그 - Java의 미래, Virtual Thread&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) &lt;a href=&quot;https://openjdk.org/jeps/444&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JEP - 444: Virtual Thread&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5) &lt;a href=&quot;https://spring.io/blog/2022/10/11/embracing-virtual-threads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Spring Blog - Embracing Virtual Threads&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/Java</category>
      <author>70825</author>
      <guid isPermaLink="true">https://hello70825.tistory.com/603</guid>
      <comments>https://hello70825.tistory.com/603#entry603comment</comments>
      <pubDate>Mon, 22 Jul 2024 16:39:57 +0900</pubDate>
    </item>
  </channel>
</rss>