<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>체셔's blog</title>
    <link>https://chessire.tistory.com/</link>
    <description>김체셔의 기술 블로그</description>
    <language>ko</language>
    <pubDate>Tue, 2 Jun 2026 09:39:48 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>체셔 Kim</managingEditor>
    <item>
      <title>OS-Level Virtualization - 가상화의 역사 3</title>
      <link>https://chessire.tistory.com/entry/os-level-virtualization</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; OS는 하나지만 경계만 여럿입니다.&lt;br /&gt;&lt;/span&gt;컨테이너는 단순한 가벼움이 아니라 다른 경계가 됩니다.&lt;br /&gt;그 경계를 만드는 것이 네임스페이스와 cgroup입니다. &lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;처음 컨테이너를 접했을 때의 잘못된 질문&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너를 처음 접했을 때, 저는 자연스럽게 VM과 비교하기 시작했습니다. 그리고 이런 식으로 정리했습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;VM은 OS까지 통째로 올리니까 무겁고, 컨테이너는 OS를 공유하니까 가볍다.&quot;&lt;/p&gt;
&lt;/blockquote&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;VM과 컨테이너는 무게가 다른 게 아니라, 경계를 어디에 그었느냐가 다른 것 아닐까?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 질문에서 출발하면 컨테이너의 구조가 훨씬 선명하게 보이기 시작했습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;VM과 컨테이너: 경계의 위치가 다릅니다&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2편에서 VM은 OS 단위로 경계를 세운다고 정리했습니다. 게스트 OS 전체가 격리의 단위였습니다. 커널이 분리되기 때문에 한 VM에서 발생한 사고가 다른 VM으로 번지지 않았습니다. 강한 격리였지만, 그만큼 운영 단위가 컸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너는 다른 선택을 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 커널은 공유합니다. 대신 그 위에서 돌아가는 프로세스(집합)를 격리합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;격리의 단위가 머신(OS)에서 프로세스로 내려온 것입니다. 커널은 하나지만, 각 컨테이너는 자신만의 독립된 세계가 있는 것처럼 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 제가 막혔던 지점이 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;커널을 공유하면 격리가 제대로 되는 건가? VM보다 경계가 약한 것 아닌가?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 의문을 풀려면 컨테이너가 경계를 어떻게 만드는지 들여다봐야 했습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;경계를 만드는 첫 번째 도구: 네임스페이스(Namespace)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너의 격리는 네임스페이스라는 Linux 커널 기능에서 시작됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네임스페이스가 하는 일은 단순합니다. 프로세스가 &lt;b&gt;볼 수 있는 범위&lt;/b&gt;를 제한합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 컨테이너 A 안에서 실행 중인 프로세스는 이렇게 동작합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자신의 PID가 1번이라고 알고 있습니다. (실제로는 호스트에서 다른 번호입니다.)&lt;/li&gt;
&lt;li&gt;자신만의 네트워크 인터페이스가 있다고 알고 있습니다.&lt;/li&gt;
&lt;li&gt;자신만의 파일 시스템 루트(/)를 가진 것처럼 동작합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 2편에서 본 VM의 게스트 OS와 비슷한 구조입니다. 차이는 커널이 분리된 것이 아니라, 커널이 제공하는 &lt;b&gt;뷰(View)만 분리&lt;/b&gt;됐다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스는 자신이 격리된 세계에 있다고 믿습니다. 실제로는 같은 커널 위에 있지만, 네임스페이스가 그 뷰를 잘라냅니다. 저는 이것이 Virtual Memory에서 봤던 구조와 같다고 느꼈습니다. 주소가 가짜였던 것처럼, 여기서는 프로세스가 보는 세계가 가짜입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네임스페이스는 컨테이너의 &lt;b&gt;경계(Boundary)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMvLBy/dJMcaibx2Ea/2YVu48a8Ew4cJHHiCqx53k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMvLBy/dJMcaibx2Ea/2YVu48a8Ew4cJHHiCqx53k/img.png&quot; data-alt=&quot;커널 하나에 여러 개의 뷰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMvLBy/dJMcaibx2Ea/2YVu48a8Ew4cJHHiCqx53k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMvLBy%2FdJMcaibx2Ea%2F2YVu48a8Ew4cJHHiCqx53k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;540&quot; height=&quot;540&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;커널 하나에 여러 개의 뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;경계에 의한 자원 배분: cgroup&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네임스페이스로 프로세스가 보는 세계를 격리했다고 해서 끝이 아니었습니다. 여기서 또 막혔습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;보이는 것만 격리하면 자원은 어떻게 나누나? 컨테이너 하나가 CPU를 다 써버리면?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하는 것이 cgroup(Control Group)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cgroup은 프로세스 집합이 &lt;b&gt;사용할 수 있는 자원의 양&lt;/b&gt;을 제한합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 컨테이너는 CPU의 몇 %까지만 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;이 컨테이너는 메모리를 얼마까지만 점유할 수 있다.&lt;/li&gt;
&lt;li&gt;이 컨테이너의 네트워크 대역폭은 여기까지다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2편에서 하이퍼바이저가 VM들의 자원 충돌을 정책으로 조정했던 것처럼, cgroup은 컨테이너 수준에서 같은 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cgroup은 컨테이너의 &lt;b&gt;정책(Policy)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컨테이너에서 경계 + 매핑 + 정책&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 편들에서 반복됐던 프레임을 컨테이너에 대입하면 이렇게 정리됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;경계(Boundary)&lt;/b&gt;: 네임스페이스가 프로세스가 볼 수 있는 범위를 자릅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매핑(Mapping)&lt;/b&gt;: 컨테이너 안의 가상 경로, 네트워크, PID가 호스트의 실제 자원과 연결됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정책(Policy)&lt;/b&gt;: cgroup이 각 컨테이너의 자원 사용량을 제한하고 조정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VM에서는 하이퍼바이저가 이 세 가지를 담당했습니다. 컨테이너에서는 Linux 커널 자체가 이 역할을 수행합니다. 별도의 하이퍼바이저 레이어 없이, 커널 기능만으로 경계와 매핑과 정책이 작동합니다. 이것이 컨테이너가 가벼운 이유입니다. 하지만 본질은 가벼움이 아니라, 경계를 어디에 그었느냐의 차이입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&quot;약한 격리 아닌가?&quot;라는 질문에 대한 답&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너가 커널을 공유한다는 사실은 분명히 VM보다 격리가 약하다는 의미이기도 합니다. 커널 취약점이 있으면 컨테이너 경계가 뚫릴 수 있습니다. VM이라면 커널이 분리되어 있어서 같은 상황에서 더 강하게 막아냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 트레이드오프는 실제로 존재합니다. 컨테이너는 격리를 포기하고 효율을 택한 것이 아닙니다. 격리의 단위를 바꾼 것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VM은 &quot;다른 머신&quot;을 만듭니다. 컨테이너는 &quot;같은 머신 안의 다른 세계&quot;를 만듭니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 쪽이 옳다는 이야기가 아닙니다. 운영하려는 단위가 무엇이냐에 따라 적합한 경계가 달라집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;요약&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컨테이너는 VM보다 가벼운 기술이 아니라, 경계를 OS에서 프로세스로 내린 기술입니다.&lt;/li&gt;
&lt;li&gt;네임스페이스가 프로세스가 볼 수 있는 범위를 격리합니다. (경계)&lt;/li&gt;
&lt;li&gt;컨테이너 안의 가상 자원은 호스트의 실제 자원과 매핑됩니다. (매핑)&lt;/li&gt;
&lt;li&gt;cgroup이 컨테이너별 자원 사용량을 제한하고 조정합니다. (정책)&lt;/li&gt;
&lt;li&gt;커널을 공유하기 때문에 격리 수준이 다르며, 이는 트레이드오프입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다음 편: Docker, 경계를 배포 단위로 굳히다&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너라는 경계가 만들어졌지만, 그것을 어떻게 묶고 옮기고 재현할 것인가는 별개의 문제였습니다. Docker는 컨테이너에 이미지라는 포장을 씌워 배포 경험을 표준화했습니다. 다음 편에서는 Docker가 컨테이너의 어떤 문제를 풀었는지 따라가보겠습니다.&lt;/p&gt;</description>
      <category>BackEnd &amp;middot; DevOps/Docker</category>
      <category>cgroup</category>
      <category>container</category>
      <category>docker</category>
      <category>Linux</category>
      <category>namespace</category>
      <category>OSVirtualization</category>
      <category>가상화</category>
      <category>격리</category>
      <category>인프라</category>
      <category>컨테이너</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/118</guid>
      <comments>https://chessire.tistory.com/entry/os-level-virtualization#entry118comment</comments>
      <pubDate>Mon, 27 Apr 2026 07:43:31 +0900</pubDate>
    </item>
    <item>
      <title>Virtual Machine은 도대체 무엇을 가상화했을까? - 가상화의 역사 2</title>
      <link>https://chessire.tistory.com/entry/virtual-machine-mapping-and-policy</link>
      <description>&lt;blockquote data-end=&quot;1111&quot; data-start=&quot;1077&quot; data-ke-style=&quot;style1&quot;&gt;VM은 OS가 보는 컴퓨터를 만듭니다.&lt;br /&gt;하이퍼 바이저가 매핑, 정책으로 운영합니다.&lt;br /&gt;그 결과, OS 단위 격리가 만들어집니다.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;h3 data-end=&quot;1111&quot; data-start=&quot;1077&quot; data-ke-size=&quot;size23&quot;&gt;1. 하드웨어 가상화라는 말은 어디까지를 포함할까?&lt;/h3&gt;
&lt;p data-end=&quot;1271&quot; data-start=&quot;1112&quot; data-ke-size=&quot;size16&quot;&gt;하드웨어 가상화라는 표현을 들으면, 흔히 CPU나 메모리 같은 부품을 소프트웨어로 그대로 재현하는 기술을 떠올리게 됩니다. 하지만 Virtual Machine(VM)을 정리하다 보니 제가 처음에 잘못된 질문을 하고 있었다는 걸 깨달았습니다. &amp;ldquo;VM은 도대체 하드웨어의 무엇을 가상화했는가?&amp;rdquo;입니다.&lt;/p&gt;
&lt;p data-end=&quot;1414&quot; data-start=&quot;1273&quot; data-ke-size=&quot;size16&quot;&gt;정리를 해보면 다음 문장에 닿게 됩니다. VM이 가상화한 대상은 CPU나 메모리 자체가 아니라, 운영체제가 하드웨어라고 전제하고 기대하는 &lt;b&gt;인터페이스 전체&lt;/b&gt;입니다. 정확히 말하면 VM은 OS가 보게 되는 한 대의 컴퓨터를 가상화합니다.&lt;/p&gt;
&lt;p data-end=&quot;1518&quot; data-start=&quot;1416&quot; data-ke-size=&quot;size16&quot;&gt;이 구조 덕분에 게스트 OS는 가상 환경임을 전제로 하지 않아도, 지금 물리 머신 위에 있다는 규약 하에 부팅하고, 드라이버를 로드하며, 스케줄링과 메모리 관리를 수행합니다.&lt;/p&gt;
&lt;hr data-end=&quot;1523&quot; data-start=&quot;1520&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1563&quot; data-start=&quot;1525&quot; data-ke-size=&quot;size23&quot;&gt;2. 운영체제가 말하는 하드웨어는 부품이 아니라 규약입니다&lt;/h3&gt;
&lt;p data-end=&quot;1653&quot; data-start=&quot;1564&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 전제를 하나 고정하고 가야 합니다. 운영체제 입장에서 하드웨어는 손에 잡히는 부품 목록이 아니라, 약속된 규약(인터페이스)들의 집합입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1858&quot; data-start=&quot;1655&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1707&quot; data-start=&quot;1655&quot;&gt;&lt;b&gt;CPU 인터페이스&lt;/b&gt;: 특권 명령 실행, 인터럽트 처리, 유저/커널 모드 전환 규칙&lt;/li&gt;
&lt;li data-end=&quot;1756&quot; data-start=&quot;1708&quot;&gt;&lt;b&gt;메모리 인터페이스&lt;/b&gt;: 주소 공간 접근 방식, 페이지 폴트 같은 이벤트 처리&lt;/li&gt;
&lt;li data-end=&quot;1809&quot; data-start=&quot;1757&quot;&gt;&lt;b&gt;I/O 인터페이스&lt;/b&gt;: 디스크&amp;middot;네트워크 장치에 데이터를 쓰고 읽는 방식(DMA 등)&lt;/li&gt;
&lt;li data-end=&quot;1858&quot; data-start=&quot;1810&quot;&gt;&lt;b&gt;부팅 인터페이스&lt;/b&gt;: 전원이 켜진 뒤 어느 지점에서 실행을 시작할지에 대한 약속&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1930&quot; data-start=&quot;1860&quot; data-ke-size=&quot;size16&quot;&gt;VM은 이 규약 묶음을 &lt;b&gt;게스트 OS마다 한 세트씩&lt;/b&gt; 제공해, OS가 &lt;b&gt;독립된 머신을 가진 것처럼&lt;/b&gt; 동작하게 만듭니다.&lt;/p&gt;
&lt;hr data-end=&quot;1935&quot; data-start=&quot;1932&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1978&quot; data-start=&quot;1937&quot; data-ke-size=&quot;size23&quot;&gt;3. 그렇다면 현실 자원(CPU/메모리/디스크)은 어떻게 공유될까?&lt;/h3&gt;
&lt;p data-end=&quot;2079&quot; data-start=&quot;1979&quot; data-ke-size=&quot;size16&quot;&gt;게스트 OS마다 &amp;ldquo;내가 주인인 머신&amp;rdquo;이 존재한다면, 그 규약을 현실의 물리 자원과 연결해 줄 구성 요소가 필요합니다. &lt;b&gt;여기서 하이퍼바이저(Hypervisor)&lt;/b&gt;가 등장합니다.&lt;/p&gt;
&lt;p data-end=&quot;2124&quot; data-start=&quot;2081&quot; data-ke-size=&quot;size16&quot;&gt;0편에서 정의했던 가상화의 3요소를 대입하면 VM의 구조는 이렇게 압축됩니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2181&quot; data-start=&quot;2126&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2181&quot; data-start=&quot;2128&quot; data-ke-size=&quot;size16&quot;&gt;VM = OS 단위의 추상화 경계 + 현실 자원을 연결하는 매핑 + 충돌을 조정하는 정책&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;2243&quot; data-start=&quot;2183&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2243&quot; data-start=&quot;2183&quot; data-ke-size=&quot;size16&quot;&gt;이 프레임을 잡고 나서야 VM이 왜 그렇게 설계됐는지가 비로소 납득됐습니다&lt;/p&gt;
&lt;hr data-end=&quot;2248&quot; data-start=&quot;2245&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2284&quot; data-start=&quot;2250&quot; data-ke-size=&quot;size23&quot;&gt;4. VM이 세운 경계: 프로세스가 아니라 OS&lt;/h3&gt;
&lt;p data-end=&quot;2331&quot; data-start=&quot;2285&quot; data-ke-size=&quot;size16&quot;&gt;VM이 제공하는 격리는 프롤로그에서 본 가상 메모리와 &lt;b&gt;격리 단위가 다릅니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;2447&quot; data-start=&quot;2333&quot; data-ke-size=&quot;size16&quot;&gt;가상 메모리가 프로세스 단위의 경계를 만들었다면, VM은 OS 단위의 경계를 세웁니다. 커널 자체가 분리되기에, 한 VM에서 발생한 커널 패닉이나 보안 사고가 다른 VM으로 번질 가능성이 크게 줄어듭니다.&lt;/p&gt;
&lt;p data-end=&quot;2546&quot; data-start=&quot;2449&quot; data-ke-size=&quot;size16&quot;&gt;즉, VM의 운영 단위는 개별 프로그램이 아니라 머신(OS 포함) 전체가 됩니다. 이 경계 덕분에 서로 다른 OS를 한 서버에서 동시에 운영할 수 있게 되었습니다.&lt;/p&gt;
&lt;hr data-end=&quot;2551&quot; data-start=&quot;2548&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2587&quot; data-start=&quot;2553&quot; data-ke-size=&quot;size23&quot;&gt;5. 경계가 생기면, 현실과 연결하는 매핑이 필요합니다&lt;/h3&gt;
&lt;p data-end=&quot;2696&quot; data-start=&quot;2588&quot; data-ke-size=&quot;size16&quot;&gt;게스트 OS가 보는 세계가 실제 자원을 쓰려면 &lt;b&gt;연결 표(매핑 테이블)&lt;/b&gt;가 작동해야 합니다. VM의 핵심 동작은 게스트의 관점을 현실의 물리 자원에 맞춰 지속적으로 &lt;b&gt;매핑&lt;/b&gt;하는 일입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2882&quot; data-start=&quot;2698&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2761&quot; data-start=&quot;2698&quot;&gt;게스트가 보는 4개의 CPU 코어는 실제 CPU의 &lt;b&gt;시간 조각(Time Slice)&lt;/b&gt;에 매핑됩니다.&lt;/li&gt;
&lt;li data-end=&quot;2816&quot; data-start=&quot;2762&quot;&gt;게스트가 물리 메모리라고 믿는 주소는 호스트 메모리의 특정 영역으로 재매핑됩니다.&lt;/li&gt;
&lt;li data-end=&quot;2882&quot; data-start=&quot;2817&quot;&gt;게스트의 디스크 쓰기 요청은 물리 장치 자체가 아니라, 호스트의 파일 또는 가상 장치 모델로 연결될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2971&quot; data-start=&quot;2884&quot; data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 자원의 복제가 아니라 &lt;b&gt;연결&lt;/b&gt;입니다. 현실 자원은 하나지만, 매핑을 통해 여러 게스트에게 각자의 자원처럼 보이게 만드는 구조입니다.&lt;/p&gt;
&lt;hr data-end=&quot;2976&quot; data-start=&quot;2973&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;3009&quot; data-start=&quot;2978&quot; data-ke-size=&quot;size23&quot;&gt;6. 여러 VM이 동시에 돌면, 정책이 필요합니다&lt;/h3&gt;
&lt;p data-end=&quot;3104&quot; data-start=&quot;3010&quot; data-ke-size=&quot;size16&quot;&gt;매핑이 가능해졌다고 해서 끝나지는 않습니다. 여러 VM이 동시에 자원을 사용하면 충돌은 피할 수 없습니다. 그래서 하이퍼바이저는 &lt;b&gt;정책(Policy)&lt;/b&gt;을 집행합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3220&quot; data-start=&quot;3106&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3145&quot; data-start=&quot;3106&quot;&gt;어떤 VM에게 CPU 시간을 우선적으로 배분할 것인가(스케줄링)&lt;/li&gt;
&lt;li data-end=&quot;3190&quot; data-start=&quot;3146&quot;&gt;특정 VM이 메모리를 어디까지 점유할 수 있게 할 것인가(제한 및 회수)&lt;/li&gt;
&lt;li data-end=&quot;3220&quot; data-start=&quot;3191&quot;&gt;네트워크 대역폭을 어떻게 나눌 것인가(QoS 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3287&quot; data-start=&quot;3222&quot; data-ke-size=&quot;size16&quot;&gt;이 구조를 따라가다 보니, 0편에서 세운 공식이 VM에서도 똑같이 나타났습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgyrtT/dJMcaf6GEwt/qlEHYBfTE9JJWVlOfkoKgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgyrtT/dJMcaf6GEwt/qlEHYBfTE9JJWVlOfkoKgK/img.png&quot; data-alt=&quot;VM은 OS가 보는 한 대의 컴퓨터를 만든다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgyrtT/dJMcaf6GEwt/qlEHYBfTE9JJWVlOfkoKgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgyrtT%2FdJMcaf6GEwt%2FqlEHYBfTE9JJWVlOfkoKgK%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;520&quot; height=&quot;520&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;VM은 OS가 보는 한 대의 컴퓨터를 만든다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-end=&quot;3292&quot; data-start=&quot;3289&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;3337&quot; data-start=&quot;3294&quot; data-ke-size=&quot;size23&quot;&gt;7. &amp;ldquo;하드웨어를 속인다&amp;rdquo;보다 정확한 표현은 &amp;ldquo;규약을 만족시킨다&amp;rdquo;입니다&lt;/h3&gt;
&lt;p data-end=&quot;3421&quot; data-start=&quot;3338&quot; data-ke-size=&quot;size16&quot;&gt;저도 처음엔 하드웨어를 속이는 기술이라고 생각했는데, 직접 파고들어 보니 더 정확한 표현이 따로 있었습니다. OS의 기대를 만족시키는기술이라고 쓰는 편이 더 정확해보입니다.&lt;/p&gt;
&lt;p data-end=&quot;3592&quot; data-start=&quot;3423&quot; data-ke-size=&quot;size16&quot;&gt;게스트 OS는 특정 명령을 실행하면 하드웨어가 정해진 방식으로 응답할 것이라는 규약을 전제로 설계되어 있습니다. 하이퍼바이저는 그 규약이 안전하게 성립하도록, 필요할 때 실행을 &lt;b&gt;트랩(Trap)&lt;/b&gt;으로 전환해 처리하거나, 하드웨어 지원(VT-x 등)을 통해 가능한 범위에서 직접 실행되도록 구성합니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;3662&quot; data-start=&quot;3594&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;3662&quot; data-start=&quot;3596&quot; data-ke-size=&quot;size16&quot;&gt;OS가 믿는 머신의 규약을 재현하고, 현실 자원으로 매핑하며, 정책으로 조정한다.&lt;br /&gt;이것이 VM의 핵심입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;3667&quot; data-start=&quot;3664&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;3690&quot; data-start=&quot;3669&quot; data-ke-size=&quot;size23&quot;&gt;8. 다음 편으로 넘어가는 질문&lt;/h3&gt;
&lt;p data-end=&quot;3781&quot; data-start=&quot;3691&quot; data-ke-size=&quot;size16&quot;&gt;VM은 OS라는 큰 경계를 세움으로써 강한 격리를 얻었습니다. 다만 운영 단위가 OS인 만큼, 상황에 따라 오버헤드가 생깁니다. 그렇다면 이런 질문이 가능합니다.&lt;/p&gt;
&lt;p data-end=&quot;3832&quot; data-start=&quot;3783&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;격리는 유지하면서, OS까지 통째로 포함하지 않고 더 가볍게 만들 순 없을까?&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;3950&quot; data-start=&quot;3834&quot; data-ke-size=&quot;size16&quot;&gt;이 고민이 바로 &lt;b&gt;컨테이너(Container)&lt;/b&gt;의 시작점입니다. 경계가 바뀌면, 매핑과 정책도 바뀝니다. 다음 편에서는 경계가 머신에서 프로세스 쪽으로 이동했을 때 무엇이 달라지는지 살펴보겠습니다.&lt;/p&gt;
&lt;hr data-end=&quot;3955&quot; data-start=&quot;3952&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;3971&quot; data-start=&quot;3957&quot; data-ke-size=&quot;size23&quot;&gt;9. 요약 (5줄)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;4187&quot; data-start=&quot;3972&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;4013&quot; data-start=&quot;3972&quot;&gt;VM은 물리 부품이 아니라 하드웨어 인터페이스 규약을 가상화합니다.&lt;/li&gt;
&lt;li data-end=&quot;4058&quot; data-start=&quot;4014&quot;&gt;운영 단위(경계)를 OS 전체로 잡기 때문에 강한 격리 능력을 갖습니다.&lt;/li&gt;
&lt;li data-end=&quot;4104&quot; data-start=&quot;4059&quot;&gt;게스트의 자원 요청은 하이퍼바이저의 매핑을 거쳐 물리 자원으로 연결됩니다.&lt;/li&gt;
&lt;li data-end=&quot;4146&quot; data-start=&quot;4105&quot;&gt;자원 공유의 질서는 하이퍼바이저가 집행하는 정책에 의해 유지됩니다.&lt;/li&gt;
&lt;li data-end=&quot;4187&quot; data-start=&quot;4147&quot;&gt;VM은 &lt;b&gt;OS의 기대를 만족시키는 인터페이스 재현 레이어&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;4230&quot; data-start=&quot;4189&quot; data-ke-size=&quot;size16&quot;&gt;다음 편: 3편. Container, 경계를 프로세스로 내려 얻은 효율성&lt;/p&gt;</description>
      <category>BackEnd &amp;middot; DevOps/Docker</category>
      <category>Abstraction</category>
      <category>hardware-interface</category>
      <category>Hypervisor</category>
      <category>indirection</category>
      <category>Isolation</category>
      <category>virtual-machine</category>
      <category>Virtualization</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/114</guid>
      <comments>https://chessire.tistory.com/entry/virtual-machine-mapping-and-policy#entry114comment</comments>
      <pubDate>Mon, 20 Apr 2026 08:11:03 +0900</pubDate>
    </item>
    <item>
      <title>첫 번째 가상화 레이어 Virtual Memory - 가상화의 역사 1</title>
      <link>https://chessire.tistory.com/entry/virtual-memory-address-space</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;주소는 가짜입니다.&lt;br /&gt;매핑과 정책이 경계를 만듭니다.&lt;br /&gt;가상화는 여기서 시작됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;h2 data-end=&quot;259&quot; data-start=&quot;210&quot; data-ke-size=&quot;size26&quot;&gt;1. &amp;ldquo;Virtual Memory가 가상화 맞아요?&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;372&quot; data-start=&quot;261&quot; data-ke-size=&quot;size16&quot;&gt;이 시리즈를 시작하며 저는 &amp;ldquo;VM &amp;rarr; 컨테이너 &amp;rarr; Docker &amp;rarr; Kubernetes&amp;rdquo; 흐름을 잡았습니다. 그런데 첫 번째 주인공으로 Virtual Memory를 꺼내면 보통 이런 질문이 돌아옵니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;453&quot; data-start=&quot;374&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;406&quot; data-start=&quot;374&quot;&gt;&amp;ldquo;메모리 관리는 그냥 OS의 기본 기능 아닌가요?&amp;rdquo;&lt;/li&gt;
&lt;li data-end=&quot;453&quot; data-start=&quot;407&quot;&gt;&amp;ldquo;본격적인 가상화 이야기로 넘어가기 전에 왜 갑자기 메모리 쪽으로 새는 거죠?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;602&quot; data-start=&quot;455&quot; data-ke-size=&quot;size16&quot;&gt;저 역시 처음에는 Virtual Memory를 &amp;lsquo;메모리 부족을 해결하는 기술&amp;rsquo; 정도로만 생각했습니다. 하지만 관점을 &lt;b&gt;[경계 + 매핑 + 정책]&lt;/b&gt;이라는 프레임으로 옮겨 보면, Virtual Memory는 오히려 가상화의 원형에 가깝다는 사실을 확인하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;614&quot; data-start=&quot;604&quot; data-ke-size=&quot;size16&quot;&gt;결론은 단순합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;759&quot; data-start=&quot;616&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;669&quot; data-start=&quot;616&quot;&gt;&lt;b&gt;경계:&lt;/b&gt; 프로세스마다 나만의 독립된 주소 공간이 존재하는 것처럼 보이게 합니다.&lt;/li&gt;
&lt;li data-end=&quot;717&quot; data-start=&quot;670&quot;&gt;&lt;b&gt;매핑:&lt;/b&gt; 가상 주소를 실제 물리 메모리 위치에 연결하는 번역층을 둡니다.&lt;/li&gt;
&lt;li data-end=&quot;759&quot; data-start=&quot;718&quot;&gt;&lt;b&gt;정책:&lt;/b&gt; 서로의 영역을 침범하지 못하도록 보호 규칙을 강제합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;834&quot; data-start=&quot;761&quot; data-ke-size=&quot;size16&quot;&gt;이 구조는 이후에 다룰 VM이나 Kubernetes에서도 이름만 바뀐 채 반복됩니다. 차이는 &amp;ldquo;무엇을 경계로 잡느냐&amp;rdquo;에 가깝습니다.&lt;/p&gt;
&lt;hr data-end=&quot;839&quot; data-start=&quot;836&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;893&quot; data-start=&quot;841&quot; data-ke-size=&quot;size26&quot;&gt;2. Virtual Memory가 만든 환상: &amp;ldquo;각 프로세스는 자기 주소 공간을 가진다&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;935&quot; data-start=&quot;895&quot; data-ke-size=&quot;size16&quot;&gt;Virtual Memory가 만든 첫 번째 효과는 단순하면서도 강합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1069&quot; data-start=&quot;937&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;986&quot; data-start=&quot;937&quot;&gt;프로세스 A는 자신이 0번지부터 끝번지까지의 메모리를 &amp;lsquo;가진 것처럼&amp;rsquo; 동작합니다.&lt;/li&gt;
&lt;li data-end=&quot;1033&quot; data-start=&quot;987&quot;&gt;프로세스 B도 똑같이 0번지를 사용하지만, A의 0번지와는 다른 세계입니다.&lt;/li&gt;
&lt;li data-end=&quot;1069&quot; data-start=&quot;1034&quot;&gt;서로의 메모리가 어디에 있는지 알 수도, 볼 수도 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1189&quot; data-start=&quot;1071&quot; data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 &lt;b&gt;주소(Address)의 의미가 바뀐다&lt;/b&gt;는 점입니다. 우리는 흔히 주소를 &amp;lsquo;실제 메모리의 물리적 위치&amp;rsquo;라고 생각합니다. 하지만 Virtual Memory에서 주소는 그렇게 취급되지 않습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1282&quot; data-start=&quot;1191&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1239&quot; data-start=&quot;1191&quot;&gt;주소는 &amp;lsquo;실제 위치&amp;rsquo;가 아니라, 자원을 식별하기 위한 &lt;b&gt;이름&lt;/b&gt;에 가깝습니다.&lt;/li&gt;
&lt;li data-end=&quot;1282&quot; data-start=&quot;1240&quot;&gt;실제 위치는 운영체제가 관리하고, 프로세스에는 이름(주소)만 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1381&quot; data-start=&quot;1284&quot; data-ke-size=&quot;size16&quot;&gt;이 순간부터 &lt;b&gt;주소 공간(Address Space)&lt;/b&gt;은 물리적 현실이 아니라 운영체제가 설계한 인터페이스가 됩니다. 저는 이 지점을 &amp;ldquo;첫 번째 가상화 레이어라고 봅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DIQZW/dJMcajnEiVh/rYLnQ9zzompDI7tMpsFdt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DIQZW/dJMcajnEiVh/rYLnQ9zzompDI7tMpsFdt1/img.png&quot; data-alt=&quot;주소는 가짜, 매핑이 진짜&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DIQZW/dJMcajnEiVh/rYLnQ9zzompDI7tMpsFdt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDIQZW%2FdJMcajnEiVh%2FrYLnQ9zzompDI7tMpsFdt1%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;480&quot; height=&quot;480&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;주소는 가짜, 매핑이 진짜&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-end=&quot;1386&quot; data-start=&quot;1383&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1434&quot; data-start=&quot;1388&quot; data-ke-size=&quot;size26&quot;&gt;3. 그럼 질문이 바뀝니다: &amp;ldquo;이름이 인터페이스라면, 실체는 누가 관리하죠?&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;1466&quot; data-start=&quot;1436&quot; data-ke-size=&quot;size16&quot;&gt;주소가 인터페이스라면 저는 이런 생각이 들었습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1541&quot; data-start=&quot;1468&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1502&quot; data-start=&quot;1468&quot;&gt;&amp;ldquo;그럼 실제 물리 메모리는 누가, 어떻게 나눠주지?&amp;rdquo;&lt;/li&gt;
&lt;li data-end=&quot;1541&quot; data-start=&quot;1503&quot;&gt;&amp;ldquo;프로세스들이 각자 주소를 쓰는데 충돌이 안 나는 이유가 뭐지?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1586&quot; data-start=&quot;1543&quot; data-ke-size=&quot;size16&quot;&gt;이 의문을 해소하면 Virtual Memory의 구조는 세 가지로 정리됩니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1616&quot; data-start=&quot;1588&quot; data-ke-size=&quot;size23&quot;&gt;3-1) 경계: 주소 공간이라는 소유권 경계&lt;/h3&gt;
&lt;p data-end=&quot;1735&quot; data-start=&quot;1617&quot; data-ke-size=&quot;size16&quot;&gt;운영체제는 각 프로세스가 볼 수 있는 주소의 범위를 논리적으로 확정합니다. 이 범위 밖은 프로세스 입장에서 원칙적으로 접근할 수 없는 영역입니다. 저는 이것을 &lt;b&gt;격리(Isolation)&lt;/b&gt;의 시작이라고 봅니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1764&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size23&quot;&gt;3-2) 매핑: 가상 주소 &amp;rarr; 물리 메모리&lt;/h3&gt;
&lt;p data-end=&quot;1889&quot; data-start=&quot;1765&quot; data-ke-size=&quot;size16&quot;&gt;운영체제는 &amp;ldquo;이 주소는 실제로 여기다&amp;rdquo;를 연결하는 매핑 정보를 유지합니다. 프로세스는 주소만 사용하고, 실제 물리적 배치는 운영체제가 결정합니다. 저는 이것이 &lt;b&gt;간접화(Indirection)&lt;/b&gt;의 핵심이라고 정리했습니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1931&quot; data-start=&quot;1891&quot; data-ke-size=&quot;size23&quot;&gt;3-3) 정책: 보호 규칙(Permission)으로 침범을 막는다&lt;/h3&gt;
&lt;p data-end=&quot;2083&quot; data-start=&quot;1932&quot; data-ke-size=&quot;size16&quot;&gt;매핑에는 위치 정보만 있는 게 아닙니다. 읽기만 가능, 쓰기 가능, 실행 가능 같은 규칙이 붙습니다. 이것은 구현 디테일을 넘어선 &lt;b&gt;정책(Policy)&lt;/b&gt;입니다. 가상화는 환상을 보여주는 것으로 끝나지 않고, 그 환상을 유지하기 위해 정책을 강제해야 합니다.&lt;/p&gt;
&lt;hr data-end=&quot;2088&quot; data-start=&quot;2085&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2135&quot; data-start=&quot;2090&quot; data-ke-size=&quot;size26&quot;&gt;4. Virtual Memory가 남긴 핵심: &amp;ldquo;환상은 운영 모델을 바꾼다&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;2158&quot; data-start=&quot;2137&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 오면 질문은 이렇게 바뀝니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2197&quot; data-start=&quot;2160&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2197&quot; data-start=&quot;2160&quot;&gt;&amp;ldquo;그래서, 주소를 가상으로 만들어서 얻는 진짜 이득이 뭔가요?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2242&quot; data-start=&quot;2199&quot; data-ke-size=&quot;size16&quot;&gt;Virtual Memory는 단순한 편의 기능을 넘어 운영 모델을 바꿨습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2375&quot; data-start=&quot;2244&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2284&quot; data-start=&quot;2244&quot;&gt;프로세스는 물리 메모리의 구조를 몰라도 됩니다. (&lt;b&gt;추상화&lt;/b&gt;)&lt;/li&gt;
&lt;li data-end=&quot;2335&quot; data-start=&quot;2285&quot;&gt;운영체제는 상황에 맞춰 데이터를 배치하거나 이동시킬 수 있습니다. (&lt;b&gt;유연성&lt;/b&gt;)&lt;/li&gt;
&lt;li data-end=&quot;2375&quot; data-start=&quot;2336&quot;&gt;잘못된 접근이나 침범은 정책 위반으로 차단됩니다. (&lt;b&gt;안정성&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2484&quot; data-start=&quot;2377&quot; data-ke-size=&quot;size16&quot;&gt;즉, 현실 자원을 직접 다루던 방식이 &lt;b&gt;[간접화 + 정책]&lt;/b&gt; 구조로 넘어간 것입니다. 저는 이 패턴이 뒤에서 다룰 VM / 컨테이너 / Kubernetes로 이어지는 &amp;ldquo;공통 골격&amp;rdquo;이라고 봤습니다.&lt;/p&gt;
&lt;hr data-end=&quot;2489&quot; data-start=&quot;2486&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2526&quot; data-start=&quot;2491&quot; data-ke-size=&quot;size26&quot;&gt;5. 오늘날의 연결: 주소 공간에서 머신으로의 확장&lt;/h2&gt;
&lt;p data-end=&quot;2616&quot; data-start=&quot;2528&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 정리하고 나서, 저는 가상화를 보는 시각이 바뀌었습니다. 가상화는 단순한 속임수가 아니라, &lt;b&gt;경계와 매핑, 그리고 정책을 통해 자원을 운영하는 시스템 설계&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;2676&quot; data-start=&quot;2618&quot; data-ke-size=&quot;size16&quot;&gt;그리고 그 첫 번째 성공 모델이 Virtual Memory였습니다. 그렇다면 다음 질문은 자연스럽습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2749&quot; data-start=&quot;2678&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2749&quot; data-start=&quot;2678&quot;&gt;&amp;ldquo;주소 공간(메모리)을 가상화할 수 있다면, CPU와 디스크를 포함한 머신 전체도 같은 방식으로 가상화할 수 있지 않을까?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2801&quot; data-start=&quot;2751&quot; data-ke-size=&quot;size16&quot;&gt;이 질문에 대한 대답이 다음 편의 주제인 &lt;b&gt;Virtual Machine(VM)&lt;/b&gt;입니다.&lt;/p&gt;</description>
      <category>Notes/Computer Science</category>
      <category>address-space</category>
      <category>indirection</category>
      <category>Isolation</category>
      <category>mapping</category>
      <category>OS</category>
      <category>virtual-memory</category>
      <category>Virtualization</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/113</guid>
      <comments>https://chessire.tistory.com/entry/virtual-memory-address-space#entry113comment</comments>
      <pubDate>Mon, 13 Apr 2026 08:21:42 +0900</pubDate>
    </item>
    <item>
      <title>하드웨어 가상화란 무엇인가? - 가상화의 역사 0</title>
      <link>https://chessire.tistory.com/entry/what-is-hardware-virtualization</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;OS까지 쪼개는 가상화&lt;br /&gt;경계를 세우는 순간 따라오는 매핑과 정책&lt;br /&gt;컨테이너, Docker, Kubernetes&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;h3 data-end=&quot;191&quot; data-start=&quot;156&quot; data-ke-size=&quot;size23&quot;&gt;1. 하드웨어 가상화는 도대체 무엇을 가상화한 걸까?&lt;/h3&gt;
&lt;p data-end=&quot;356&quot; data-start=&quot;193&quot; data-ke-size=&quot;size16&quot;&gt;하드웨어 가상화라는 단어를 처음 접하면 보통 비슷한 이미지를 떠올리게 됩니다. CPU나 메모리를 교묘하게 속이는 기술 같은 느낌 말입니다. 하지만 이 개념을 파고들다 보면 정작 중요한 질문은 다른 곳에 있다는 것을 알게 됩니다. 대체 무엇을 하드웨어처럼 보이게 만들고 싶었던 걸까?&lt;/p&gt;
&lt;p data-end=&quot;496&quot; data-start=&quot;358&quot; data-ke-size=&quot;size16&quot;&gt;저도 처음엔 복잡하게 접근했는데, 파고들수록 오히려 단순한 질문으로 좁혀졌습니다. 바로 한 대의 물리 머신 위에 여러 대의 머신이 있는 것처럼 보이게 만드는 구조입니다. 여기서 말하는 머신은 단순한 프로그램 하나가 아니라, OS까지 포함한 실행 환경 전체를 의미했습니다.&lt;/p&gt;
&lt;p data-end=&quot;583&quot; data-start=&quot;498&quot; data-ke-size=&quot;size16&quot;&gt;결국 하드웨어 가상화라는 말은, 사실상 OS 단위의 경계를 하나 더 만드는 작업에 가까웠습니다. 근데 여기서 저는 한 가지가 걸렸습니다.&lt;/p&gt;
&lt;p data-end=&quot;654&quot; data-start=&quot;585&quot; data-ke-size=&quot;size16&quot;&gt;OS를 통째로 올리는 건 너무 무겁지 않았을까?&lt;br /&gt;그냥 프로세스만 잘 돌리면 충분했을 텐데, 왜 굳이 이런 선택을 했을까?&lt;/p&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;656&quot; data-ke-size=&quot;size16&quot;&gt;그래서 저는 경계를 어디에 그었는지부터 먼저 따라가봤습니다.&lt;/p&gt;
&lt;hr data-end=&quot;707&quot; data-start=&quot;704&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;735&quot; data-start=&quot;709&quot; data-ke-size=&quot;size23&quot;&gt;2. 하드웨어 가상화를 왜 쓰게 됐을까?&lt;/h3&gt;
&lt;p data-end=&quot;865&quot; data-start=&quot;737&quot; data-ke-size=&quot;size16&quot;&gt;단순히 &amp;ldquo;필요해서 썼다&amp;rdquo;는 설명은 큰 도움이 되지 않았습니다. 구체적으로 어떤 불편함이 우리를 OS까지 통째로 가두는 구조로 이끌었는지 들여다볼 필요가 있었습니다. 그 불편함의 장면들을 복기해 보면 세 가지 키워드가 선명해집니다.&lt;/p&gt;
&lt;h4 data-end=&quot;905&quot; data-start=&quot;867&quot; data-ke-size=&quot;size20&quot;&gt;(1) 같이 돌리면 같이 망가지는 순간 (Isolation)&lt;/h4&gt;
&lt;p data-end=&quot;1063&quot; data-start=&quot;907&quot; data-ke-size=&quot;size16&quot;&gt;서버 한 대에서 여러 서비스를 돌리다 보면, 한쪽의 자원 폭주가 전체 시스템을 흔들어놓는 장면을 흔히 봅니다. 프로세스 수준에서 주의를 기울이는 것만으로는 해결되지 않는 결함들이 존재했습니다. 그래서 아예 운영 단위를 OS 레벨에서 격리해버리는 선택이 매력적으로 다가왔던 겁니다.&lt;/p&gt;
&lt;h4 data-end=&quot;1103&quot; data-start=&quot;1065&quot; data-ke-size=&quot;size20&quot;&gt;(2) 환경이 다르면 생기는 끝없는 변수 (Illusion)&lt;/h4&gt;
&lt;p data-end=&quot;1270&quot; data-start=&quot;1105&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;내 로컬 PC에서는 잘 되는데요&amp;rdquo;라는 말이 운영 환경에서 통하지 않을 때의 당혹감은 익숙합니다. OS 버전, 라이브러리, 미세한 설정 차이가 결과값을 바꿨습니다. 결국 프로그램만 옮기는 게 아니라, 그 프로그램이 믿고 있는 환경 자체를 복제해 일관된 실행 환경을 만들어낼 필요가 있었습니다.&lt;/p&gt;
&lt;h4 data-end=&quot;1316&quot; data-start=&quot;1272&quot; data-ke-size=&quot;size20&quot;&gt;(3) 하드웨어가 바뀌면 위쪽도 흔들리는 구조 (Indirection)&lt;/h4&gt;
&lt;p data-end=&quot;1433&quot; data-start=&quot;1318&quot; data-ke-size=&quot;size16&quot;&gt;서버를 교체하거나 스토리지 구성이 바뀔 때마다 상위 서비스가 영향을 받는다면 운영의 유연성은 떨어질 수밖에 없습니다. 인프라와 서비스 사이의 직접적인 연결을 끊어줄 간접화의 층이 절실해진 지점이었습니다.&lt;/p&gt;
&lt;p data-end=&quot;1542&quot; data-start=&quot;1435&quot; data-ke-size=&quot;size16&quot;&gt;그런데 여기서 또 막혔습니다. 격리(Isolation)만 잘하면 되는 것 아닐까? 왜 환상(Illusion)과 간접화(Indirection)는 항상 세트처럼 따라다니는 걸까?&lt;/p&gt;
&lt;hr data-end=&quot;1547&quot; data-start=&quot;1544&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1603&quot; data-start=&quot;1549&quot; data-ke-size=&quot;size23&quot;&gt;3. 왜 Illusion / Isolation / Indirection은 늘 한 세트일까?&lt;/h3&gt;
&lt;p data-end=&quot;1687&quot; data-start=&quot;1605&quot; data-ke-size=&quot;size16&quot;&gt;이건 철학의 문제라기보다, 구조를 따라가다 보면 자연스럽게 그렇게 보였습니다. 격리를 위해 경계를 긋는 순간, 연쇄적인 반응이 시작되기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;1713&quot; data-start=&quot;1689&quot; data-ke-size=&quot;size16&quot;&gt;격리를 하려면 명확한 경계(Boundary)를 세워야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;1839&quot; data-start=&quot;1715&quot; data-ke-size=&quot;size16&quot;&gt;경계를 세우고 나면, 그 경계 안에서 보이는 자원과 실제 물리 자원을 연결하는 매핑(Mapping)이 필요해집니다. (이 연결을 상위 레이어 관점에서 보면 환상이 되고, 구조 관점에서 보면 간접화가 됩니다.)&lt;/p&gt;
&lt;p data-end=&quot;1901&quot; data-start=&quot;1841&quot; data-ke-size=&quot;size16&quot;&gt;매핑이 생겨 자원을 공유하기 시작하면, 이를 공정하게 나누기 위한 정책(Policy)이 필요해집니다.&lt;/p&gt;
&lt;p data-end=&quot;2001&quot; data-start=&quot;1903&quot; data-ke-size=&quot;size16&quot;&gt;격리라는 목표를 세우는 순간, 환상과 간접화, 그리고 정책이 따라오는 것은 매우 자연스러운 흐름이었습니다. 이 과정을 거치면 가상화의 정체가 하나의 명료한 문장으로 정리됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2069&quot; data-start=&quot;2003&quot; data-ke-size=&quot;size16&quot;&gt;가상화는 결국 &lt;b&gt;경계(Boundary) + 매핑(Mapping) + 정책(Policy)&lt;/b&gt;으로 굴러가는 구조였습니다.&lt;/p&gt;
&lt;hr data-end=&quot;2074&quot; data-start=&quot;2071&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2114&quot; data-start=&quot;2076&quot; data-ke-size=&quot;size23&quot;&gt;4. VM에서 &amp;ldquo;경계 + 매핑 + 정책&amp;rdquo;은 어떤 모습이었을까?&lt;/h3&gt;
&lt;p data-end=&quot;2158&quot; data-start=&quot;2116&quot; data-ke-size=&quot;size16&quot;&gt;이 구조를 구체적인 가상 머신(VM)의 모습에 대입해 보면 더 명확해집니다.&lt;/p&gt;
&lt;h4 data-end=&quot;2196&quot; data-start=&quot;2160&quot; data-ke-size=&quot;size20&quot;&gt;(1) 경계(Boundary): 운영 단위를 OS로 설정&lt;/h4&gt;
&lt;p data-end=&quot;2290&quot; data-start=&quot;2198&quot; data-ke-size=&quot;size16&quot;&gt;하드웨어 가상화는 격리의 단위를 프로세스가 아닌 머신(OS 포함)으로 잡았습니다. 무겁다는 단점이 있지만, 경계가 매우 선명하고 강력하다는 확실한 이점을 얻었습니다.&lt;/p&gt;
&lt;h4 data-end=&quot;2330&quot; data-start=&quot;2292&quot; data-ke-size=&quot;size20&quot;&gt;(2) 매핑(Mapping): 가상 자원을 현실 자원에 연결&lt;/h4&gt;
&lt;p data-end=&quot;2484&quot; data-start=&quot;2332&quot; data-ke-size=&quot;size16&quot;&gt;VM 안의 CPU, 메모리, 디스크가 실제로 작동하려면 물리 자원과의 연결이 필요합니다. 가상 디스크가 실제 스토리지의 어디에 위치하는지, 네트워크 패킷이 어떤 물리 스위치로 나가는지를 관리하는 식입니다. 이 매핑(연결)을 유지하는 여러 구성요소가 가상화를 지탱합니다.&lt;/p&gt;
&lt;h4 data-end=&quot;2518&quot; data-start=&quot;2486&quot; data-ke-size=&quot;size20&quot;&gt;(3) 정책(Policy): 공유를 위한 의사결정&lt;/h4&gt;
&lt;p data-end=&quot;2629&quot; data-start=&quot;2520&quot; data-ke-size=&quot;size16&quot;&gt;자원을 나눠 쓰는 순간 결정해야 할 것들이 폭발합니다. CPU 시간을 어떻게 쪼갤지, 메모리 할당량을 어디까지 허용할지, 특정 VM의 폭주를 어떻게 제한할지 같은 정책들이 시스템의 핵심이 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2691&quot; data-start=&quot;2631&quot; data-ke-size=&quot;size16&quot;&gt;결국 하드웨어 가상화는 단순한 기술이 아니라, 공유를 안전하게 운영하기 위한 제어/관리 계층에 가까웠습니다.&lt;/p&gt;
&lt;hr data-end=&quot;2696&quot; data-start=&quot;2693&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kx9Ze/dJMb99L8pEY/cCb5Rk7XmuSEVxqbzEujC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kx9Ze/dJMb99L8pEY/cCb5Rk7XmuSEVxqbzEujC1/img.png&quot; data-alt=&quot;가상화는 경계를 만들고, 매팡하고, 정책으로 운영한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kx9Ze/dJMb99L8pEY/cCb5Rk7XmuSEVxqbzEujC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKx9Ze%2FdJMb99L8pEY%2FcCb5Rk7XmuSEVxqbzEujC1%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;520&quot; height=&quot;520&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가상화는 경계를 만들고, 매팡하고, 정책으로 운영한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;2750&quot; data-start=&quot;2698&quot; data-ke-size=&quot;size23&quot;&gt;5. VM에서 Container, Kubernetes로 이어지는 흐름: 경계의 이동&lt;/h3&gt;
&lt;p data-end=&quot;2859&quot; data-start=&quot;2752&quot; data-ke-size=&quot;size16&quot;&gt;VM을 이렇게 구조적으로 이해하고 나면, 컨테이너나 쿠버네티스로 이어지는 역사가 단순히 더 가벼운 기술의 등장이 아님을 깨닫게 됩니다. 핵심은 경계의 위치가 어디로 움직였느냐에 있었습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3130&quot; data-start=&quot;2861&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2908&quot; data-start=&quot;2861&quot;&gt;&lt;b&gt;Virtual Memory:&lt;/b&gt; 경계가 주소 공간(프로세스)에 생겼습니다.&lt;/li&gt;
&lt;li data-end=&quot;2965&quot; data-start=&quot;2909&quot;&gt;&lt;b&gt;VM(하드웨어 가상화):&lt;/b&gt; 경계를 머신(OS) 전체로 끌어올려 강력한 격리를 얻었습니다.&lt;/li&gt;
&lt;li data-end=&quot;3019&quot; data-start=&quot;2966&quot;&gt;&lt;b&gt;Container:&lt;/b&gt; 경계를 다시 프로세스(집합) 단위로 내려 효율성을 챙겼습니다.&lt;/li&gt;
&lt;li data-end=&quot;3078&quot; data-start=&quot;3020&quot;&gt;&lt;b&gt;Docker:&lt;/b&gt; 그 경계를 배포 가능한 패키지로 굳혀 배포 경험을 표준화하고 단순화했습니다.&lt;/li&gt;
&lt;li data-end=&quot;3130&quot; data-start=&quot;3079&quot;&gt;&lt;b&gt;Kubernetes:&lt;/b&gt; 경계를 개별 서버를 넘어 클러스터 운영 단위로 확장했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3302&quot; data-start=&quot;3132&quot; data-ke-size=&quot;size16&quot;&gt;결국 가상화의 역사는 운영 단위를 무엇으로 잡느냐가 이동해 온 과정이었습니다. 기술이 완전히 바뀐 것이 아니라, 경계/매핑/정책이라는 틀을 유지한 채 운영의 단위만 옮겨 다니며 진화해 온 역사였던 셈입니다. 이 흐름을 파악하고 나면 현대 인프라 기술들의 연결 고리가 비로소 매끄럽게 보이기 시작합니다.&lt;/p&gt;
&lt;hr data-end=&quot;3307&quot; data-start=&quot;3304&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;3328&quot; data-start=&quot;3309&quot; data-ke-size=&quot;size23&quot;&gt;6. 요약 및 다음 편 예고&lt;/h3&gt;
&lt;p data-end=&quot;3360&quot; data-start=&quot;3330&quot; data-ke-size=&quot;size16&quot;&gt;오늘 정리해 본 내용을 다섯 줄로 요약하면 이렇습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3583&quot; data-start=&quot;3362&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3403&quot; data-start=&quot;3362&quot;&gt;하드웨어 가상화는 OS(머신) 단위로 경계를 세우는 방식이었습니다.&lt;/li&gt;
&lt;li data-end=&quot;3445&quot; data-start=&quot;3404&quot;&gt;격리를 시작하면 매핑이 필요해지고, 자연스럽게 정책이 따라붙습니다.&lt;/li&gt;
&lt;li data-end=&quot;3500&quot; data-start=&quot;3446&quot;&gt;따라서 가상화는 &amp;ldquo;경계 + 매핑 + 정책&amp;rdquo;의 구조로 이해하는 것이 가장 깔끔합니다.&lt;/li&gt;
&lt;li data-end=&quot;3541&quot; data-start=&quot;3501&quot;&gt;VM에서 쿠버네티스까지의 발전은 이 경계가 이동해 온 역사입니다.&lt;/li&gt;
&lt;li data-end=&quot;3583&quot; data-start=&quot;3542&quot;&gt;이 패턴을 이해하면 어떤 가상화 기술도 구조적으로 분석할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3704&quot; data-start=&quot;3585&quot; data-ke-size=&quot;size16&quot;&gt;다음 편에서는 이 모든 패턴이 처음으로 가장 선명하게 나타났던 지점을 살펴보려 합니다. 바로 Virtual Memory입니다. 주소 공간이라는 첫 번째 가상화 레이어가 어떤 힌트를 주었는지 함께 따라가 보겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;3704&quot; data-start=&quot;3585&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3767&quot; data-start=&quot;3706&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 편:&lt;/b&gt; 가상화의 역사 1편. 첫번째 가상화 레이어 Virtual Memory&lt;/p&gt;</description>
      <category>BackEnd &amp;middot; DevOps/Docker</category>
      <category>container</category>
      <category>docker</category>
      <category>hardware-virtualization</category>
      <category>Hypervisor</category>
      <category>indirection</category>
      <category>Isolation</category>
      <category>kubernetes</category>
      <category>virtual-layer</category>
      <category>Virtualization</category>
      <category>vm</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/112</guid>
      <comments>https://chessire.tistory.com/entry/what-is-hardware-virtualization#entry112comment</comments>
      <pubDate>Mon, 6 Apr 2026 07:53:15 +0900</pubDate>
    </item>
    <item>
      <title>Atomic: 락이 아니라 캐시 라인 소유권 경쟁이다.</title>
      <link>https://chessire.tistory.com/entry/atomic-cache-line-ownership-competition</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Serif KR';&quot;&gt; 멀티스레드는 더 많은 코어가 아니라&lt;br /&gt;더 적은 공유 write로 빨라집니다. &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;멀티스레드에서 제일 흔한 착각이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-5-2-thinking&quot; data-message-id=&quot;9bffcce2-dfa0-46b1-86c6-9c7312c36a4a&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;blockquote data-end=&quot;156&quot; data-start=&quot;122&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;156&quot; data-start=&quot;124&quot; data-ke-size=&quot;size16&quot;&gt;atomic이 느린 이유 = 락(lock) 때문&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;251&quot; data-start=&quot;158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;251&quot; data-start=&quot;158&quot; data-ke-size=&quot;size16&quot;&gt;아니요. 많은 경우 atomic이 느린 이유는 락이 아니라,&lt;br /&gt;&lt;b&gt;캐시 라인 소유권(ownership) 경쟁&lt;/b&gt; 때문에 생기는 &lt;b&gt;coherency 트래픽&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;277&quot; data-start=&quot;253&quot; data-ke-size=&quot;size16&quot;&gt;3편에서 본 규칙을 그대로 가져오면 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;371&quot; data-start=&quot;279&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;304&quot; data-start=&quot;279&quot;&gt;read는 공유(S)로 버틸 수 있지만&lt;/li&gt;
&lt;li data-end=&quot;329&quot; data-start=&quot;305&quot;&gt;write는 독점(M/E)을 요구하고&lt;/li&gt;
&lt;li data-end=&quot;371&quot; data-start=&quot;330&quot;&gt;누가 write를 시작하면 다른 코어의 라인은 invalidate 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;447&quot; data-start=&quot;373&quot; data-ke-size=&quot;size16&quot;&gt;atomic은 여기서 한 단계 더 빡셉니다.&lt;br /&gt;atomic은 보통 &lt;b&gt;RMW(Read-Modify-Write)&lt;/b&gt; 이기 때문입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L6HbC/dJMcahcfJqQ/BUKX2CEifxeKQkydPHNvq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L6HbC/dJMcahcfJqQ/BUKX2CEifxeKQkydPHNvq1/img.png&quot; data-alt=&quot;Write 1번으로 캐시 라인 소유권 전쟁이 시작한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L6HbC/dJMcahcfJqQ/BUKX2CEifxeKQkydPHNvq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL6HbC%2FdJMcahcfJqQ%2FBUKX2CEifxeKQkydPHNvq1%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;640&quot; height=&quot;349&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Write 1번으로 캐시 라인 소유권 전쟁이 시작한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr data-end=&quot;452&quot; data-start=&quot;449&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;496&quot; data-start=&quot;454&quot; data-ke-size=&quot;size26&quot;&gt;1) atomic이 비싼 진짜 이유: RMW는 라인 독점을 강제한다&lt;/h2&gt;
&lt;p data-end=&quot;531&quot; data-start=&quot;498&quot; data-ke-size=&quot;size16&quot;&gt;atomic_fetch_add 같은 연산을 생각해봅시다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;567&quot; data-start=&quot;533&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;544&quot; data-start=&quot;533&quot;&gt;값을 읽고&lt;/li&gt;
&lt;li data-end=&quot;555&quot; data-start=&quot;545&quot;&gt;수정하고&lt;/li&gt;
&lt;li data-end=&quot;567&quot; data-start=&quot;556&quot;&gt;다시 쓴다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;627&quot; data-start=&quot;569&quot; data-ke-size=&quot;size16&quot;&gt;이 3단계를 중간에 끼어들지 못하게 보장해야 합니다.&lt;br /&gt;그래서 하드웨어는 대체로 다음을 요구합니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;673&quot; data-start=&quot;629&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;673&quot; data-start=&quot;631&quot; data-ke-size=&quot;size16&quot;&gt;해당 캐시 라인을 내가 독점(M/E)해야만 RMW를 수행할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;714&quot; data-start=&quot;675&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;714&quot; data-start=&quot;675&quot; data-ke-size=&quot;size16&quot;&gt;문제는 여러 코어가 같은 atomic을 동시에 건드릴 때 터집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;833&quot; data-start=&quot;716&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;750&quot; data-start=&quot;716&quot;&gt;Core0가 라인 독점 &amp;rarr; Core1은 invalidate&lt;/li&gt;
&lt;li data-end=&quot;785&quot; data-start=&quot;751&quot;&gt;Core1이 라인 독점 &amp;rarr; Core0는 invalidate&lt;/li&gt;
&lt;li data-end=&quot;833&quot; data-start=&quot;786&quot;&gt;결과: &lt;b&gt;라인이 ping-pong&lt;/b&gt; (False Sharing과 구조가 동일)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;846&quot; data-start=&quot;835&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 결론:&lt;/p&gt;
&lt;blockquote data-end=&quot;914&quot; data-start=&quot;848&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;914&quot; data-start=&quot;850&quot; data-ke-size=&quot;size16&quot;&gt;atomic 경쟁(contended atomic)은 연산 비용이 아니라 라인 이동 비용으로 느려진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;991&quot; data-start=&quot;916&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;991&quot; data-start=&quot;916&quot; data-ke-size=&quot;size16&quot;&gt;그래서 스레드를 늘리면 오히려 느려지는 현상이 나옵니다.&lt;br /&gt;CPU가 일을 더 하는 게 아니라, &lt;b&gt;서로 밀어내느라&lt;/b&gt; 시간을 씁니다.&lt;/p&gt;
&lt;hr data-end=&quot;996&quot; data-start=&quot;993&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1050&quot; data-start=&quot;998&quot; data-ke-size=&quot;size26&quot;&gt;2) Uncontended atomic vs Contended atomic (진단 기준)&lt;/h2&gt;
&lt;p data-end=&quot;1083&quot; data-start=&quot;1052&quot; data-ke-size=&quot;size16&quot;&gt;atomic이 항상 나쁜 건 아닙니다. 구분이 필요합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1117&quot; data-start=&quot;1085&quot; data-ke-size=&quot;size23&quot;&gt;Uncontended atomic (경쟁 없음)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1172&quot; data-start=&quot;1118&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1144&quot; data-start=&quot;1118&quot;&gt;한 코어만 해당 atomic을 자주 업데이트&lt;/li&gt;
&lt;li data-end=&quot;1172&quot; data-start=&quot;1145&quot;&gt;또는 업데이트 빈도가 낮아서 충돌이 거의 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1192&quot; data-start=&quot;1174&quot; data-ke-size=&quot;size16&quot;&gt;이 경우는 대체로 괜찮습니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1224&quot; data-start=&quot;1194&quot; data-ke-size=&quot;size23&quot;&gt;Contended atomic (경쟁 있음)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1313&quot; data-start=&quot;1225&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1264&quot; data-start=&quot;1225&quot;&gt;여러 스레드가 같은 atomic(같은 캐시 라인)을 고빈도로 RMW&lt;/li&gt;
&lt;li data-end=&quot;1313&quot; data-start=&quot;1265&quot;&gt;대표: 전역 카운터, 전역 큐 인덱스, 글로벌 통계, 글로벌 work counter&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1378&quot; data-start=&quot;1315&quot; data-ke-size=&quot;size16&quot;&gt;이 경우는 거의 확실히 병목입니다.&lt;br /&gt;&lt;b&gt;락이 없어도 느립니다.&lt;/b&gt; (락이 아니라 coherency 경쟁이니까)&lt;/p&gt;
&lt;hr data-end=&quot;1383&quot; data-start=&quot;1380&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1424&quot; data-start=&quot;1385&quot; data-ke-size=&quot;size26&quot;&gt;3) 처방의 방향은 단 하나: 공유 write-hot을 없애라&lt;/h2&gt;
&lt;p data-end=&quot;1447&quot; data-start=&quot;1426&quot; data-ke-size=&quot;size16&quot;&gt;4편의 실전 처방은 여기로 수렴합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1554&quot; data-start=&quot;1449&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1482&quot; data-start=&quot;1449&quot;&gt;공유 write-hot을 &lt;b&gt;스레드 로컬로 분해&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1515&quot; data-start=&quot;1483&quot;&gt;필요한 순간에만 &lt;b&gt;합친다(reduction)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1554&quot; data-start=&quot;1516&quot;&gt;합치는 지점도 가능하면 &lt;b&gt;저빈도 / 배치(batch)&lt;/b&gt;로 만든다&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1580&quot; data-start=&quot;1556&quot; data-ke-size=&quot;size16&quot;&gt;즉, atomic을 잘 쓰는 법이 아니라&lt;/p&gt;
&lt;blockquote data-end=&quot;1614&quot; data-start=&quot;1582&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1614&quot; data-start=&quot;1584&quot; data-ke-size=&quot;size16&quot;&gt;atomic을 &amp;lsquo;뜨거운 루프에서&amp;rsquo; 치워버리는 법&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1624&quot; data-start=&quot;1616&quot; data-ke-size=&quot;size16&quot;&gt;이 핵심입니다.&lt;/p&gt;
&lt;hr data-end=&quot;1629&quot; data-start=&quot;1626&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1689&quot; data-start=&quot;1631&quot; data-ke-size=&quot;size26&quot;&gt;4) 처방 1: per-thread counter + reduction (가장 강력하고 가장 흔함)&lt;/h2&gt;
&lt;h4 data-end=&quot;1722&quot; data-start=&quot;1691&quot; data-ke-size=&quot;size20&quot;&gt;나쁜 예: 모든 스레드가 전역 atomic++&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1770788550587&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std::atomic&amp;lt;uint64_t&amp;gt; gCount = 0;
void Worker()
{
	for (...)
    {
    	gCount.fetch_add(1, std::memory_order_relaxed);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1909&quot; data-start=&quot;1866&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 연산이 아니라 &lt;b&gt;라인 소유권 ping-pong&lt;/b&gt;으로 느려집니다.&lt;/p&gt;
&lt;h4 data-end=&quot;1952&quot; data-start=&quot;1911&quot; data-ke-size=&quot;size20&quot;&gt;좋은 예: 스레드 로컬 누적 + 마지막 합산(reduction)&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1770787912662&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std::atomic&amp;lt;uint64_t&amp;gt; gCount = 0;
void Worker()
{
	uint64_t local = 0;
    for (...)
    {
    	local++;
    }
    gCount.fetch_add(local, std::memory_order_relaxed); // 빈도 1회
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2208&quot; data-start=&quot;2146&quot; data-ke-size=&quot;size16&quot;&gt;핵심은 fetch_add 횟수를 줄이는 게 아닙니다.&lt;br /&gt;&lt;b&gt;라인 소유권 경쟁을 루프 밖으로 빼는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2246&quot; data-start=&quot;2210&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2246&quot; data-start=&quot;2212&quot; data-ke-size=&quot;size16&quot;&gt;전역 atomic은 루프마다가 아니라 배치로 접근하라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;2251&quot; data-start=&quot;2248&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2314&quot; data-start=&quot;2253&quot; data-ke-size=&quot;size26&quot;&gt;5) 처방 2: per-thread data layout (스레드별 write-hot을 구조적으로 분리)&lt;/h2&gt;
&lt;p data-end=&quot;2392&quot; data-start=&quot;2316&quot; data-ke-size=&quot;size16&quot;&gt;reduction이 항상 가능한 건 아닙니다.&lt;br /&gt;큐 인덱스, 작업 분배, 스레드 상태처럼 실시간으로 공유해야 하는 값이 존재합니다.&lt;/p&gt;
&lt;p data-end=&quot;2413&quot; data-start=&quot;2394&quot; data-ke-size=&quot;size16&quot;&gt;이때는 최소한 이렇게 해야 합니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2461&quot; data-start=&quot;2415&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2461&quot; data-start=&quot;2417&quot; data-ke-size=&quot;size16&quot;&gt;서로 다른 스레드가 쓰는 데이터가 같은 캐시 라인에 들어가지 않게 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;2511&quot; data-start=&quot;2463&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2511&quot; data-start=&quot;2463&quot; data-ke-size=&quot;size16&quot;&gt;즉, 2편에서 다룬 alignas(64)의 진짜 목적이 여기서 다시 등장합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;2546&quot; data-start=&quot;2513&quot; data-ke-size=&quot;size23&quot;&gt;패턴: thread slot을 캐시 라인 단위로 고정&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1770787878185&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct alignas(64) ThreadSlot
{
	uint64_t counter; // padding은 컴파일러/플랫폼에 따라 달라질 수 있음
    char pad[64 - sizeof(uint64_t)];
};

ThreadSlot slots[MAX_THREADS];
void Worker(int tid)
{
	for (...)
    {
    	slots[tid].counter++; // 각자 자기 라인만 건드림
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2875&quot; data-start=&quot;2818&quot; data-ke-size=&quot;size16&quot;&gt;이 설계는 속도 최적화라기보다&lt;br /&gt;&lt;b&gt;coherency 트래픽 최악 케이스 제거(안정화)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-end=&quot;2880&quot; data-start=&quot;2877&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2923&quot; data-start=&quot;2882&quot; data-ke-size=&quot;size26&quot;&gt;6) 처방 3: 큐/링버퍼는 head/tail(메타데이터)을 분리하라&lt;/h2&gt;
&lt;p data-end=&quot;2970&quot; data-start=&quot;2925&quot; data-ke-size=&quot;size16&quot;&gt;Lock-free 큐에서 흔한 병목은 알고리즘이 아니라 메타데이터 배치입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3080&quot; data-start=&quot;2972&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2999&quot; data-start=&quot;2972&quot;&gt;head와 tail이 같은 캐시 라인에 있으면&lt;/li&gt;
&lt;li data-end=&quot;3037&quot; data-start=&quot;3000&quot;&gt;producer/consumer가 서로 다른 변수를 업데이트해도&lt;/li&gt;
&lt;li data-end=&quot;3080&quot; data-start=&quot;3038&quot;&gt;같은 라인을 두고 ping-pong이 납니다 (False Sharing)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;3088&quot; data-start=&quot;3082&quot; data-ke-size=&quot;size23&quot;&gt;원칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3156&quot; data-start=&quot;3089&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3120&quot; data-start=&quot;3089&quot;&gt;&lt;b&gt;head와 tail을 다른 캐시 라인으로 분리&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;3156&quot; data-start=&quot;3121&quot;&gt;size/flags 같은 write-hot 메타데이터도 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3188&quot; data-start=&quot;3158&quot; data-ke-size=&quot;size16&quot;&gt;이건 구조가 복잡해지기 전에 적용할수록 효과가 큽니다.&lt;/p&gt;
&lt;hr data-end=&quot;3193&quot; data-start=&quot;3190&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3232&quot; data-start=&quot;3195&quot; data-ke-size=&quot;size26&quot;&gt;7) atomic을 써야 한다면: 최소한 이 관점으로 사용해라&lt;/h2&gt;
&lt;p data-end=&quot;3282&quot; data-start=&quot;3234&quot; data-ke-size=&quot;size16&quot;&gt;atomic을 완전히 없앨 수 없는 경우도 있습니다.&lt;br /&gt;그럴 때의 원칙은 단순합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;3313&quot; data-start=&quot;3284&quot; data-ke-size=&quot;size23&quot;&gt;(1) hot loop에서 atomic을 빼라&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3353&quot; data-start=&quot;3314&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3353&quot; data-start=&quot;3314&quot;&gt;루프 안에서 1회를 루프 밖에서 1회로 바꿔라 (batch)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;3380&quot; data-start=&quot;3355&quot; data-ke-size=&quot;size23&quot;&gt;(2) 공유 write-hot을 줄여라&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3412&quot; data-start=&quot;3381&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3412&quot; data-start=&quot;3381&quot;&gt;write 빈도를 낮추거나, 스레드별로 나누고 합쳐라&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;3448&quot; data-start=&quot;3414&quot; data-ke-size=&quot;size23&quot;&gt;(3) 같은 라인을 두 스레드가 건드리지 않게 배치하라&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3495&quot; data-start=&quot;3449&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3466&quot; data-start=&quot;3449&quot;&gt;per-thread slot&lt;/li&gt;
&lt;li data-end=&quot;3495&quot; data-start=&quot;3467&quot;&gt;alignas(64) 또는 명시적 padding&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3539&quot; data-start=&quot;3497&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 하면 atomic이 락처럼 느려지는 대부분의 상황은 정리됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;3544&quot; data-start=&quot;3541&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3581&quot; data-start=&quot;3546&quot; data-ke-size=&quot;size26&quot;&gt;8) 체크리스트: 이 조건이면 atomic 병목을 의심해라&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3722&quot; data-start=&quot;3583&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3623&quot; data-start=&quot;3583&quot;&gt;스레드를 늘렸는데 throughput이 거의 안 오르거나 떨어진다&lt;/li&gt;
&lt;li data-end=&quot;3657&quot; data-start=&quot;3624&quot;&gt;전역 카운터/통계/큐 인덱스가 hot path에 있다&lt;/li&gt;
&lt;li data-end=&quot;3694&quot; data-start=&quot;3658&quot;&gt;프로파일에서 모두가 같은 위치를 건드린다는 냄새가 난다&lt;/li&gt;
&lt;li data-end=&quot;3722&quot; data-start=&quot;3695&quot;&gt;락은 없는데도 CPU가 바쁘고 일이 안 끝난다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3741&quot; data-start=&quot;3724&quot; data-ke-size=&quot;size16&quot;&gt;이때는 먼저 묻는 게 맞습니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;3787&quot; data-start=&quot;3743&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;3787&quot; data-start=&quot;3745&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;나는 지금 연산을 하고 있나, 아니면 캐시 라인 소유권을 주고받고 있나?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;3792&quot; data-start=&quot;3789&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3815&quot; data-start=&quot;3794&quot; data-ke-size=&quot;size26&quot;&gt;마무리: 멀티스레드 최적화의 본질&lt;/h2&gt;
&lt;p data-end=&quot;3840&quot; data-start=&quot;3816&quot; data-ke-size=&quot;size16&quot;&gt;시리즈를 4편까지 오면 결론은 선명해집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;4033&quot; data-start=&quot;3842&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3879&quot; data-start=&quot;3842&quot;&gt;1편: CPU는 연산보다 &lt;b&gt;물류(메모리/캐시)&lt;/b&gt;가 문제다&lt;/li&gt;
&lt;li data-end=&quot;3940&quot; data-start=&quot;3880&quot;&gt;2편: 멀티코어는 &lt;b&gt;shared cache line&lt;/b&gt; 때문에 무너진다 (False Sharing)&lt;/li&gt;
&lt;li data-end=&quot;3988&quot; data-start=&quot;3941&quot;&gt;3편: Invalidate는 감이 아니라 &lt;b&gt;MESI 규칙&lt;/b&gt;으로 발생한다&lt;/li&gt;
&lt;li data-end=&quot;4033&quot; data-start=&quot;3989&quot;&gt;4편(오늘): atomic의 비용은 락이 아니라 &lt;b&gt;라인 소유권 경쟁&lt;/b&gt;이다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;4052&quot; data-start=&quot;4035&quot; data-ke-size=&quot;size16&quot;&gt;그래서 실전 처방도 단순합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;4170&quot; data-start=&quot;4054&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;4080&quot; data-start=&quot;4054&quot;&gt;공유 write-hot을 없애라&lt;/li&gt;
&lt;li data-end=&quot;4120&quot; data-start=&quot;4081&quot;&gt;스레드별로 누적하고 마지막에 합쳐라(reduction)&lt;/li&gt;
&lt;li data-end=&quot;4170&quot; data-start=&quot;4121&quot;&gt;어쩔 수 없이 공유하면 라인을 분리하라(alignas(64), layout)&lt;/li&gt;
&lt;/ol&gt;
&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #1a5490;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이전글&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Notes/Computer Science</category>
      <category>cache</category>
      <category>CacheLine</category>
      <category>CacheLineOwnership</category>
      <category>CPU</category>
      <category>DataLayout</category>
      <category>invalidate</category>
      <category>Reduction</category>
      <category>멀티스레딩</category>
      <category>멀티코어</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/110</guid>
      <comments>https://chessire.tistory.com/entry/atomic-cache-line-ownership-competition#entry110comment</comments>
      <pubDate>Mon, 30 Mar 2026 07:35:57 +0900</pubDate>
    </item>
    <item>
      <title>Invalidate를 줄이는 법: MESI로 이해하는 캐시 라인 소유권 경쟁</title>
      <link>https://chessire.tistory.com/entry/mesi-invalidate-cache-line-ownership</link>
      <description>&lt;blockquote data-end=&quot;174&quot; data-start=&quot;98&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다른 코어가 같은 캐시 라인을 가진 상태에서,&lt;br /&gt;누군가 그 라인을 write(특히 RMW)로 독점하려는 순간.&lt;br /&gt;Invalidate가 터진다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-end=&quot;174&quot; data-start=&quot;98&quot; data-ke-size=&quot;size16&quot;&gt;우리는 False Sharing을 캐시 라인 ping-pong으로 봤습니다.&lt;br /&gt;그런데 여기서 한 단계 더 정확해져야 해요.&lt;/p&gt;
&lt;blockquote data-end=&quot;233&quot; data-start=&quot;176&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;233&quot; data-start=&quot;178&quot; data-ke-size=&quot;size16&quot;&gt;Invalidate는 캐시 미스가 아니라, 쓰기 권한(소유권) 경쟁 때문에 발생한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;335&quot; data-start=&quot;235&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;335&quot; data-start=&quot;235&quot; data-ke-size=&quot;size16&quot;&gt;즉, 멀티코어에서 느려지는 이유는 데이터가 멀리 있어서가 아니라&lt;br /&gt;&lt;b&gt;누가 그 캐시 라인을 &amp;lsquo;쓰기 가능한 최신 상태&amp;rsquo;로 갖고 있느냐&lt;/b&gt;를 맞추느라 트래픽이 터지기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;364&quot; data-start=&quot;337&quot; data-ke-size=&quot;size16&quot;&gt;이걸 설명하는 최소 모델이 &lt;b&gt;MESI&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-end=&quot;369&quot; data-start=&quot;366&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;393&quot; data-start=&quot;371&quot; data-ke-size=&quot;size26&quot;&gt;0) MESI를 한 문장으로 정의&lt;/h2&gt;
&lt;p data-end=&quot;441&quot; data-start=&quot;394&quot; data-ke-size=&quot;size16&quot;&gt;캐시 라인(보통 64B)마다 CPU는 &amp;ldquo;이 라인이 지금 어떤 상태인가&amp;rdquo;를 관리합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;612&quot; data-start=&quot;443&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;493&quot; data-start=&quot;443&quot;&gt;&lt;b&gt;M (Modified)&lt;/b&gt;: 내가 수정했고(Dirty), 최신. 다른 코어는 못 가짐&lt;/li&gt;
&lt;li data-end=&quot;542&quot; data-start=&quot;494&quot;&gt;&lt;b&gt;E (Exclusive)&lt;/b&gt;: 나만 가지고 있고 최신. 아직 수정은 안 했음&lt;/li&gt;
&lt;li data-end=&quot;580&quot; data-start=&quot;543&quot;&gt;&lt;b&gt;S (Shared)&lt;/b&gt;: 여러 코어가 읽기용으로 공유 중&lt;/li&gt;
&lt;li data-end=&quot;612&quot; data-start=&quot;581&quot;&gt;&lt;b&gt;I (Invalid)&lt;/b&gt;: 무효(없다고 봐도 됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;627&quot; data-start=&quot;614&quot; data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 딱 하나:&lt;/p&gt;
&lt;blockquote data-end=&quot;726&quot; data-start=&quot;629&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;726&quot; data-start=&quot;631&quot; data-ke-size=&quot;size16&quot;&gt;쓰기(write)는 &amp;lsquo;독점(Exclusive)&amp;rsquo; 상태를 요구한다.&lt;br /&gt;그래서 누가 쓰려고 하면, 다른 코어의 같은 라인은 Invalidate(I) 된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;731&quot; data-start=&quot;728&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;773&quot; data-start=&quot;733&quot; data-ke-size=&quot;size26&quot;&gt;1) 읽기만 하면 보통 큰 싸움이 없다 (Read / Read)&lt;/h2&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;774&quot; data-ke-size=&quot;size16&quot;&gt;두 코어가 같은 주소 X를 &lt;b&gt;읽기만&lt;/b&gt; 한다고 하자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;865&quot; data-start=&quot;806&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;838&quot; data-start=&quot;806&quot;&gt;Core0: X를 읽음 &amp;rarr; E 또는 S (상황에 따라)&lt;/li&gt;
&lt;li data-end=&quot;865&quot; data-start=&quot;839&quot;&gt;Core1: X를 읽음 &amp;rarr; 둘 다 S로 수렴&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;950&quot; data-start=&quot;867&quot; data-ke-size=&quot;size16&quot;&gt;여기서는 보통 &lt;b&gt;Invalidate 폭발이 없습니다.&lt;/b&gt;&lt;br /&gt;왜냐하면 읽기는 최신성만 맞으면 되고, &lt;b&gt;독점 소유권이 필요 없기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;987&quot; data-start=&quot;952&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;987&quot; data-start=&quot;954&quot; data-ke-size=&quot;size16&quot;&gt;결론: &lt;b&gt;Read-mostly 공유는 비교적 안전&lt;/b&gt;하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;992&quot; data-start=&quot;989&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mFgNC/dJMcabb2ipe/Q4ZaaxQgKCDAGBZwTM7yT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mFgNC/dJMcabb2ipe/Q4ZaaxQgKCDAGBZwTM7yT0/img.png&quot; data-alt=&quot;Write 독점 경쟁 &amp;amp;rarr; Invalidate &amp;amp;rarr; Ping-Pong (MESI)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mFgNC/dJMcabb2ipe/Q4ZaaxQgKCDAGBZwTM7yT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmFgNC%2FdJMcabb2ipe%2FQ4ZaaxQgKCDAGBZwTM7yT0%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;480&quot; height=&quot;480&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Write 독점 경쟁 &amp;rarr; Invalidate &amp;rarr; Ping-Pong (MESI)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-end=&quot;1049&quot; data-start=&quot;994&quot; data-ke-size=&quot;size26&quot;&gt;2) 누군가 쓰기를 하는 순간부터 Invalidate가 시작된다 (Read / Write)&lt;/h2&gt;
&lt;p data-end=&quot;1092&quot; data-start=&quot;1050&quot; data-ke-size=&quot;size16&quot;&gt;이제 Core1이 X를 &lt;b&gt;write&lt;/b&gt; 한다고 하자. (X++ 같은 수정)&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;1094&quot; data-ke-size=&quot;size16&quot;&gt;이미 Core0이 X를 S 상태로 갖고 있었다면?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1201&quot; data-start=&quot;1123&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1165&quot; data-start=&quot;1123&quot;&gt;Core1은 쓰기 위해 X를 &lt;b&gt;독점 상태(M / E)&lt;/b&gt;로 만들어야 함&lt;/li&gt;
&lt;li data-end=&quot;1201&quot; data-start=&quot;1166&quot;&gt;그래서 Core0의 X는 &lt;b&gt;I(Invalid)&lt;/b&gt; 로 바뀜&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1216&quot; data-start=&quot;1203&quot; data-ke-size=&quot;size16&quot;&gt;즉, 규칙은 간단합니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;1283&quot; data-start=&quot;1218&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1283&quot; data-start=&quot;1220&quot; data-ke-size=&quot;size16&quot;&gt;다른 코어가 같은 캐시 라인을 가지고 있는데, 누군가 write를 하려는 순간 &amp;rarr; Invalidate 발생&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1367&quot; data-start=&quot;1285&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1367&quot; data-start=&quot;1285&quot; data-ke-size=&quot;size16&quot;&gt;이때 Core0는 내 캐시에 분명히 있었는데(I로 바뀌어서) 다시 가져와야 하고,&lt;br /&gt;이게 &lt;b&gt;Coherency Miss&lt;/b&gt;로 관측됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;1372&quot; data-start=&quot;1369&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1423&quot; data-start=&quot;1374&quot; data-ke-size=&quot;size26&quot;&gt;3) 최악은 Write / Write: 소유권이 공처럼 튕긴다 (Ping-Pong)&lt;/h2&gt;
&lt;p data-end=&quot;1454&quot; data-start=&quot;1424&quot; data-ke-size=&quot;size16&quot;&gt;False Sharing이 터지는 대표 상황이 이거죠.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1532&quot; data-start=&quot;1456&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1492&quot; data-start=&quot;1456&quot;&gt;Core0: 라인 X의 어떤 필드(변수 A)를 계속 write&lt;/li&gt;
&lt;li data-end=&quot;1532&quot; data-start=&quot;1493&quot;&gt;Core1: 같은 라인 X의 다른 필드(변수 B)를 계속 write&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1576&quot; data-start=&quot;1534&quot; data-ke-size=&quot;size16&quot;&gt;둘은 논리적으로 다른 변수지만, &lt;b&gt;캐시 라인이 같으면 같은 전쟁&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;1590&quot; data-start=&quot;1578&quot; data-ke-size=&quot;size16&quot;&gt;흐름은 이렇게 됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1730&quot; data-start=&quot;1592&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1635&quot; data-start=&quot;1592&quot;&gt;Core0 write &amp;rarr; X를 M로 만든다 (Core1 쪽 X는 I)&lt;/li&gt;
&lt;li data-end=&quot;1682&quot; data-start=&quot;1636&quot;&gt;Core1 write &amp;rarr; X를 M로 만들려 한다 &amp;rarr; Core0 쪽 X는 I&lt;/li&gt;
&lt;li data-end=&quot;1730&quot; data-start=&quot;1683&quot;&gt;Core0 write &amp;rarr; 다시 독점 필요 &amp;rarr; Core1 쪽 I&lt;br /&gt;&amp;hellip; 무한 반복&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1744&quot; data-start=&quot;1732&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 포인트:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1811&quot; data-start=&quot;1746&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1767&quot; data-start=&quot;1746&quot;&gt;&lt;b&gt;값 자체의 충돌이 없어도&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1789&quot; data-start=&quot;1768&quot;&gt;&lt;b&gt;캐시 라인 소유권&lt;/b&gt; 때문에&lt;/li&gt;
&lt;li data-end=&quot;1811&quot; data-start=&quot;1790&quot;&gt;Invalidate가 매번 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end=&quot;1879&quot; data-start=&quot;1813&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1879&quot; data-start=&quot;1815&quot; data-ke-size=&quot;size16&quot;&gt;결론: False Sharing은 shared data가 아니라 shared cache line 문제다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;1884&quot; data-start=&quot;1881&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1930&quot; data-start=&quot;1886&quot; data-ke-size=&quot;size26&quot;&gt;4) 왜 RMW(atomic)이 특히 비싼가: 독점 + 순서를 강제한다&lt;/h2&gt;
&lt;p data-end=&quot;1975&quot; data-start=&quot;1931&quot; data-ke-size=&quot;size16&quot;&gt;다음 편에서 atomic을 깊게 다루겠지만, 원리만 여기서 박아두면 이렇습니다.&lt;/p&gt;
&lt;p data-end=&quot;2042&quot; data-start=&quot;1977&quot; data-ke-size=&quot;size16&quot;&gt;atomic_fetch_add 같은 연산은 단순 write가 아니라 &lt;b&gt;Read-Modify-Write&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2069&quot; data-start=&quot;2044&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2051&quot; data-start=&quot;2044&quot;&gt;값을 읽고&lt;/li&gt;
&lt;li data-end=&quot;2058&quot; data-start=&quot;2052&quot;&gt;수정하고&lt;/li&gt;
&lt;li data-end=&quot;2069&quot; data-start=&quot;2059&quot;&gt;다시 쓰는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2143&quot; data-start=&quot;2071&quot; data-ke-size=&quot;size16&quot;&gt;이건 의미상 중간에 다른 코어가 끼면 안 되기 때문에,&lt;br /&gt;하드웨어는 보통 해당 라인을 &lt;b&gt;더 강하게 독점&lt;/b&gt;하려고 합니다.&lt;/p&gt;
&lt;p data-end=&quot;2173&quot; data-start=&quot;2145&quot; data-ke-size=&quot;size16&quot;&gt;즉, 경쟁 상황에서 atomic은 이렇게 동작해요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2285&quot; data-start=&quot;2175&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2203&quot; data-start=&quot;2175&quot;&gt;여러 코어가 동일 라인에 대해 RMW를 시도&lt;/li&gt;
&lt;li data-end=&quot;2237&quot; data-start=&quot;2204&quot;&gt;각 코어가 &amp;ldquo;내가 지금 독점해서 처리해야 함&amp;rdquo;을 강제&lt;/li&gt;
&lt;li data-end=&quot;2285&quot; data-start=&quot;2238&quot;&gt;결과적으로 &lt;b&gt;invalidate + 소유권 이동&lt;/b&gt;이 더 자주, 더 비싸게 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2330&quot; data-start=&quot;2287&quot; data-ke-size=&quot;size16&quot;&gt;그래서 atomic 비용을 락이니까 느리다고만 보면 진단이 반쯤 틀립니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2393&quot; data-start=&quot;2332&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2393&quot; data-start=&quot;2334&quot; data-ke-size=&quot;size16&quot;&gt;atomic의 핵심 비용은 락이 아니라, 캐시 라인 소유권 경쟁(= coherency 트래픽)이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;2410&quot; data-start=&quot;2395&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2410&quot; data-start=&quot;2395&quot; data-ke-size=&quot;size16&quot;&gt;이게 4편의 주제가 됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;2415&quot; data-start=&quot;2412&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2441&quot; data-start=&quot;2417&quot; data-ke-size=&quot;size26&quot;&gt;5) 이 규칙을 코딩 관점으로 번역하면&lt;/h2&gt;
&lt;p data-end=&quot;2497&quot; data-start=&quot;2442&quot; data-ke-size=&quot;size16&quot;&gt;MESI를 외우는 목적은 상태도를 잘 그리자는 게 아닙니다.&lt;br /&gt;코드를 이렇게 분류하기 위해서예요.&lt;/p&gt;
&lt;h3 data-end=&quot;2516&quot; data-start=&quot;2499&quot; data-ke-size=&quot;size23&quot;&gt;안전한 패턴(대체로)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2588&quot; data-start=&quot;2517&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2551&quot; data-start=&quot;2517&quot;&gt;&lt;b&gt;read-mostly 공유&lt;/b&gt; (초기화 후 읽기 전용)&lt;/li&gt;
&lt;li data-end=&quot;2588&quot; data-start=&quot;2552&quot;&gt;스레드마다 &lt;b&gt;자기 데이터에 write&lt;/b&gt; (서로 다른 라인)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;2613&quot; data-start=&quot;2590&quot; data-ke-size=&quot;size23&quot;&gt;위험한 패턴(거의 확실히 터짐)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2719&quot; data-start=&quot;2614&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2640&quot; data-start=&quot;2614&quot;&gt;여러 스레드가 &lt;b&gt;같은 라인에 write&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2678&quot; data-start=&quot;2641&quot;&gt;서로 다른 변수라도 &lt;b&gt;같은 캐시 라인&lt;/b&gt;이면 동일하게 위험&lt;/li&gt;
&lt;li data-end=&quot;2719&quot; data-start=&quot;2679&quot;&gt;경쟁 상황의 &lt;b&gt;atomic RMW&lt;/b&gt; (특히 hot counter)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2760&quot; data-start=&quot;2721&quot; data-ke-size=&quot;size16&quot;&gt;여기서 2편에서 말한 alignas(64)가 다시 의미를 갖습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2871&quot; data-start=&quot;2762&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2789&quot; data-start=&quot;2762&quot;&gt;alignas(64)는 단순히 빠르게 하는 것이 아니라&lt;/li&gt;
&lt;li data-end=&quot;2836&quot; data-start=&quot;2790&quot;&gt;&lt;b&gt;write-hot 데이터가 같은 캐시 라인을 공유하지 않게&lt;/b&gt; 하는 장치&lt;/li&gt;
&lt;li data-end=&quot;2871&quot; data-start=&quot;2837&quot;&gt;즉 &lt;b&gt;Invalidate 규칙을 회피하는 설계&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-start=&quot;2412&quot; data-end=&quot;2415&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;여기까지 정리하면, 멀티스레드에서 성능이 무너지는 이유는 CPU가 느려서가 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-5-2-thinking&quot; data-message-id=&quot;73312a82-3fcd-4bfe-b3d9-24dea9c3a379&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;p data-end=&quot;104&quot; data-start=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;대부분은 &lt;b&gt;캐시 라인(64B) 소유권을 두고 벌어지는 규칙적인 싸움&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;289&quot; data-start=&quot;106&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;140&quot; data-start=&quot;106&quot;&gt;읽기(Read)는 공유(S)로 공존할 수 있지만&lt;/li&gt;
&lt;li data-end=&quot;173&quot; data-start=&quot;141&quot;&gt;쓰기(Write)는 독점(M/E)을 요구하고&lt;/li&gt;
&lt;li data-end=&quot;219&quot; data-start=&quot;174&quot;&gt;그 순간 다른 코어의 동일 라인은 &lt;b&gt;Invalidate(I)&lt;/b&gt; 됩니다.&lt;/li&gt;
&lt;li data-end=&quot;289&quot; data-start=&quot;220&quot;&gt;이 Invalidate가 반복되면, 우리가 2편에서 본 &lt;b&gt;ping-pong(= False Sharing)&lt;/b&gt;이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;367&quot; data-start=&quot;291&quot; data-ke-size=&quot;size16&quot;&gt;즉, False Sharing은 공유 데이터 문제가 아니라&lt;br /&gt;&lt;b&gt;공유된 캐시 라인(shared cache line)&lt;/b&gt; 문제입니다.&lt;/p&gt;
&lt;p data-end=&quot;390&quot; data-start=&quot;369&quot; data-ke-size=&quot;size16&quot;&gt;이제 다음 질문이 자연스럽게 남습니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;433&quot; data-start=&quot;392&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;433&quot; data-start=&quot;394&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;그럼 atomic은 왜 이렇게 비싼가? 락이 없는데도 왜 느려지나?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;585&quot; data-start=&quot;435&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;585&quot; data-start=&quot;435&quot; data-ke-size=&quot;size16&quot;&gt;답은 이미 보입니다. atomic은 단순 write가 아니라 RMW(Read-Modify-Write)이고,&lt;br /&gt;RMW는 캐시 라인의 &lt;b&gt;독점 소유권과 순서&lt;/b&gt;를 더 강하게 요구합니다.&lt;br /&gt;그래서 병목은 락이 아니라 &lt;b&gt;coherency 트래픽&lt;/b&gt;으로 나타납니다.&lt;/p&gt;
&lt;p data-end=&quot;610&quot; data-start=&quot;587&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;p data-ke-size=&quot;size16&quot;&gt;atomic의 비용을 락이 아니라 캐시 라인 소유권 경쟁으로 재정의하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실전에서 바로 쓰는 &lt;b&gt;per-thread data layout / reduction 패턴&lt;/b&gt;으로&lt;br /&gt;멀티스레드 성능을 안정화하는 방법까지 마무리하겠습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Notes/Computer Science</category>
      <category>atomic</category>
      <category>cache</category>
      <category>CacheLine</category>
      <category>CacheLineOwnership</category>
      <category>CoherencyMiss</category>
      <category>CPU</category>
      <category>invalidate</category>
      <category>MESI</category>
      <category>멀티스레딩</category>
      <category>멀티코어</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/109</guid>
      <comments>https://chessire.tistory.com/entry/mesi-invalidate-cache-line-ownership#entry109comment</comments>
      <pubDate>Thu, 26 Mar 2026 08:16:23 +0900</pubDate>
    </item>
    <item>
      <title>AI를 쓰는데도 포트폴리오가 안 나오는 이유</title>
      <link>https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow</link>
      <description>&lt;blockquote data-end=&quot;336&quot; data-start=&quot;290&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;도구가 없어서 막히는 게 아닙니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;넘기는 방식이 틀려서 막히는 겁니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-end=&quot;412&quot; data-start=&quot;338&quot; data-ke-size=&quot;size16&quot;&gt;이미 ChatGPT도 써봤고, Claude도 써봤고, 결과물도 몇 번 뽑아봤습니다.&lt;br /&gt;그런데 이상하게 포트폴리오는 잘 안 나옵니다.&lt;/p&gt;
&lt;p data-end=&quot;412&quot; data-start=&quot;338&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;503&quot; data-start=&quot;414&quot; data-ke-size=&quot;size16&quot;&gt;초안은 나옵니다.&lt;br /&gt;문장도 그럴듯합니다.&lt;br /&gt;근데 내 경험처럼 안 느껴지고, 다시 읽어보면 붕 떠 있고, 조금만 수정하려고 해도 처음부터 다시 손대게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;503&quot; data-start=&quot;414&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;523&quot; data-start=&quot;505&quot; data-ke-size=&quot;size16&quot;&gt;그래서 결국 이런 상태가 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;602&quot; data-start=&quot;525&quot; data-ke-size=&quot;size16&quot;&gt;만든 건 있는데 정리가 안 되고,&lt;br /&gt;정리하려고 하면 문장이 내 것이 아니고,&lt;br /&gt;AI를 썼는데도 작업 속도는 빨라진 것 같지 않은 상태.&lt;/p&gt;
&lt;p data-end=&quot;602&quot; data-start=&quot;525&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;620&quot; data-start=&quot;604&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 그 이유를 다룹니다.&lt;/p&gt;
&lt;hr data-end=&quot;625&quot; data-start=&quot;622&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;blockquote data-end=&quot;708&quot; data-start=&quot;627&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;708&quot; data-start=&quot;629&quot; data-ke-size=&quot;size16&quot;&gt;이 글에서 다루는 것&lt;br /&gt;브리핑 설계, 단위 쪼개기, 교차검증.&lt;br /&gt;이 세 가지를 갖추면 같은 AI를 써도 결과물이 달라집니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;713&quot; data-start=&quot;710&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4112O/dJMcahcGOVu/kjoyaNv0lHr6u2PC6E4g9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4112O/dJMcahcGOVu/kjoyaNv0lHr6u2PC6E4g9k/img.png&quot; data-alt=&quot;AI를 활용해 데이터를 문서로 만들자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4112O/dJMcahcGOVu/kjoyaNv0lHr6u2PC6E4g9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4112O%2FdJMcahcGOVu%2FkjoyaNv0lHr6u2PC6E4g9k%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;1376&quot; height=&quot;768&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AI를 활용해 데이터를 문서로 만들자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-end=&quot;741&quot; data-start=&quot;715&quot; data-ke-size=&quot;size26&quot;&gt;처음 상태: 없는 게 아니라 흩어져 있었다&lt;/h2&gt;
&lt;p data-end=&quot;767&quot; data-start=&quot;743&quot; data-ke-size=&quot;size16&quot;&gt;최근 함께 작업한 분도 비슷한 상태였습니다.&lt;/p&gt;
&lt;p data-end=&quot;880&quot; data-start=&quot;769&quot; data-ke-size=&quot;size16&quot;&gt;AI를 아예 안 써본 분은 아니었습니다.&lt;br /&gt;이미 여러 툴을 써봤고, 결과물도 어느 정도 뽑아본 상태였습니다.&lt;br /&gt;프로젝트 경험도 있었고, 정리해둔 노션도 있었고, 작업 중 남겨둔 기록도 있었습니다.&lt;/p&gt;
&lt;p data-end=&quot;917&quot; data-start=&quot;882&quot; data-ke-size=&quot;size16&quot;&gt;문제는 그게 &lt;b&gt;보여줄 수 있는 구조&lt;/b&gt;가 아니었다는 점입니다.&lt;/p&gt;
&lt;p data-end=&quot;917&quot; data-start=&quot;882&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1044&quot; data-start=&quot;919&quot; data-ke-size=&quot;size16&quot;&gt;어딘가에는 다 있었습니다.&lt;/p&gt;
&lt;p data-end=&quot;1044&quot; data-start=&quot;919&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 설명도 있었고, 배운 점도 있었고, 작업 과정도 있었고, 생각한 흔적도 있었습니다.&lt;br /&gt;그런데 그것들이 포트폴리오 문서가 아니라 &lt;b&gt;작업 중인 사람의 메모 상태&lt;/b&gt;로 흩어져 있었습니다.&lt;/p&gt;
&lt;p data-end=&quot;1067&quot; data-start=&quot;1046&quot; data-ke-size=&quot;size16&quot;&gt;많은 사람들이 여기서 이렇게 말합니다.&lt;/p&gt;
&lt;p data-end=&quot;1084&quot; data-start=&quot;1069&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;아직 보여줄 게 없어요.&amp;rdquo;&lt;/p&gt;
&lt;p data-end=&quot;1144&quot; data-start=&quot;1086&quot; data-ke-size=&quot;size16&quot;&gt;그런데 실제로는 없는 경우보다,&lt;br /&gt;&lt;b&gt;있는데 아직 보여줄 수 있는 형태가 아닌 경우&lt;/b&gt;가 더 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;1144&quot; data-start=&quot;1086&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1241&quot; data-start=&quot;1146&quot; data-ke-size=&quot;size16&quot;&gt;포트폴리오에서 상대가 보고 싶은 건 결과물만이 아닙니다.&lt;br /&gt;이 사람이 어떤 기준으로 판단했고, 어떤 맥락에서 만들었고, 무엇을 강점으로 가져가려는지가 읽히는 구조입니다.&lt;/p&gt;
&lt;p data-end=&quot;1349&quot; data-start=&quot;1243&quot; data-ke-size=&quot;size16&quot;&gt;그 구조가 없으면, 만든 게 많아도 포트폴리오가 없는 것처럼 느껴집니다.&lt;br /&gt;그리고 그 상태로 AI에 넘기면 결과가 붕 뜹니다.&lt;br /&gt;AI는 비어 있는 맥락을 자기 방식으로 메우기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;1349&quot; data-start=&quot;1243&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1416&quot; data-start=&quot;1351&quot; data-ke-size=&quot;size16&quot;&gt;그 기본값은 대체로 비슷합니다.&lt;br /&gt;어디서 본 것 같은 문장들, 평균적인 자기소개, 무난하지만 힘이 없는 포트폴리오.&lt;/p&gt;
&lt;hr data-end=&quot;1421&quot; data-start=&quot;1418&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1437&quot; data-start=&quot;1423&quot; data-ke-size=&quot;size26&quot;&gt;브리핑이 빠져 있었다&lt;/h2&gt;
&lt;p data-end=&quot;1518&quot; data-start=&quot;1439&quot; data-ke-size=&quot;size16&quot;&gt;세션에서 가장 먼저 한 일은 AI에게 문장을 시키는 게 아니었습니다.&lt;br /&gt;그 전에 &lt;b&gt;AI가 무엇을 기준으로 봐야 하는지부터 정리&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-end=&quot;1518&quot; data-start=&quot;1439&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1531&quot; data-start=&quot;1520&quot; data-ke-size=&quot;size16&quot;&gt;핵심은 브리핑입니다.&lt;/p&gt;
&lt;p data-end=&quot;1624&quot; data-start=&quot;1533&quot; data-ke-size=&quot;size16&quot;&gt;AI는 내가 어떤 사람인지 모릅니다.&lt;br /&gt;이 문서를 누가 읽는지, 어떤 포지션을 목표로 하는지, 어디까지 강조해야 하는지, 무엇은 넣으면 안 되는지 알지 못합니다.&lt;/p&gt;
&lt;p data-end=&quot;1692&quot; data-start=&quot;1626&quot; data-ke-size=&quot;size16&quot;&gt;이 정보 없이 요청하면, AI는 빠진 맥락을 알아서 채웁니다.&lt;br /&gt;문제는 그 채움이 내 상황에 맞지 않는다는 점입니다.&lt;/p&gt;
&lt;p data-end=&quot;1722&quot; data-start=&quot;1694&quot; data-ke-size=&quot;size16&quot;&gt;브리핑에 최소한 들어가야 하는 것은 네 가지입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1853&quot; data-start=&quot;1724&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1760&quot; data-start=&quot;1724&quot;&gt;&lt;b&gt;역할&lt;/b&gt;: AI가 어떤 시점에서 이 작업을 봐야 하는지&lt;/li&gt;
&lt;li data-end=&quot;1785&quot; data-start=&quot;1761&quot;&gt;&lt;b&gt;독자&lt;/b&gt;: 이 문서를 누가 읽는지&lt;/li&gt;
&lt;li data-end=&quot;1816&quot; data-start=&quot;1786&quot;&gt;&lt;b&gt;목적&lt;/b&gt;: 이 문서가 어떤 상황에서 쓰이는지&lt;/li&gt;
&lt;li data-end=&quot;1853&quot; data-start=&quot;1817&quot;&gt;&lt;b&gt;제약 조건&lt;/b&gt;: 길이, 형식, 제외해야 할 것 같은 경계선&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1873&quot; data-start=&quot;1855&quot; data-ke-size=&quot;size16&quot;&gt;이 차이는 생각보다 크게 납니다.&lt;/p&gt;
&lt;p data-end=&quot;1906&quot; data-start=&quot;1875&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 많은 사람이 실제로는 이런 식으로 요청합니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2047&quot; data-start=&quot;1908&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1978&quot; data-start=&quot;1910&quot; data-ke-size=&quot;size16&quot;&gt;브리핑이 약한 요청&lt;br /&gt;&lt;br /&gt;&amp;ldquo;커리어 전환용 포트폴리오 자기소개 문단 써줘. 이전 경력도 강점으로 녹이고 싶어.&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-end=&quot;2047&quot; data-start=&quot;1986&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; &amp;ldquo;다양한 경험을 바탕으로 문제 해결에 강점을 가진 지원자입니다. 이전 경력을 통해 쌓은 역량을 바탕으로&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;2122&quot; data-start=&quot;2049&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2122&quot; data-start=&quot;2049&quot; data-ke-size=&quot;size16&quot;&gt;틀린 말은 아닙니다.&lt;br /&gt;문제는 &lt;b&gt;누구에게 어떻게 읽혀야 하는지&lt;/b&gt;가 빠져 있어서, 결과가 무난한 평균값으로 떨어진다는 점입니다.&lt;/p&gt;
&lt;p data-end=&quot;2149&quot; data-start=&quot;2124&quot; data-ke-size=&quot;size16&quot;&gt;같은 내용을 이렇게 바꾸면 결과가 달라집니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2476&quot; data-start=&quot;2151&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2368&quot; data-start=&quot;2153&quot; data-ke-size=&quot;size16&quot;&gt;브리핑이 갖춰진 요청&lt;br /&gt;&lt;br /&gt;&amp;ldquo;나는 7년 리테일 도메인 경력이 있는 커리어 전환 취준생이야.&lt;br /&gt;지원 포지션은 백엔드고, 이전 경력이 &amp;lsquo;잡경험&amp;rsquo;이 아니라 도메인 이해로 읽혀야 해.&lt;br /&gt;독자는 스타트업 개발팀장이고, 포트폴리오 첫 문단에 들어갈 소개 문장이라 두 줄 이내로 써줘.&lt;br /&gt;추상적인 성실함보다, 왜 이 경력이 개발 판단에 연결되는지가 드러났으면 좋겠어.&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-end=&quot;2476&quot; data-start=&quot;2376&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; &amp;ldquo;리테일 현장에서 쌓은 7년의 도메인 이해가 API와 데이터 흐름을 설계할 때의 판단 기준이 됩니다. 현업 맥락을 놓치지 않는 백엔드 개발자로 전환하는 것이 제 포지션입니다.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;2500&quot; data-start=&quot;2478&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2500&quot; data-start=&quot;2478&quot; data-ke-size=&quot;size16&quot;&gt;세션에서도 이 차이를 바로 확인했습니다.&lt;/p&gt;
&lt;p data-end=&quot;2591&quot; data-start=&quot;2502&quot; data-ke-size=&quot;size16&quot;&gt;브리핑 없이 뽑은 결과물은 문장 자체는 멀쩡했지만, 누구에게 어떤 강점으로 읽혀야 하는지가 흐렸습니다.&lt;br /&gt;반대로 브리핑을 갖춘 뒤의 문장은 훨씬 선명했습니다.&lt;/p&gt;
&lt;p data-end=&quot;2604&quot; data-start=&quot;2593&quot; data-ke-size=&quot;size16&quot;&gt;반응도 명확했습니다.&lt;/p&gt;
&lt;p data-end=&quot;2604&quot; data-start=&quot;2593&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2629&quot; data-start=&quot;2606&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;아, 이게 제가 하고 싶었던 말이에요.&amp;rdquo;&lt;/p&gt;
&lt;p data-end=&quot;2694&quot; data-start=&quot;2631&quot; data-ke-size=&quot;size16&quot;&gt;좋은 결과물은 보통 문장을 잘 써서 나오는 게 아닙니다.&lt;br /&gt;&lt;b&gt;앞에서 무엇을 분명하게 넘겼느냐&lt;/b&gt;에서 갈립니다.&lt;/p&gt;
&lt;hr data-end=&quot;2699&quot; data-start=&quot;2696&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2724&quot; data-start=&quot;2701&quot; data-ke-size=&quot;size26&quot;&gt;단위를 쪼개지 않으면 AI도 흐려진다&lt;/h2&gt;
&lt;p data-end=&quot;2799&quot; data-start=&quot;2726&quot; data-ke-size=&quot;size16&quot;&gt;브리핑이 정리되었다고 바로 문서 전체를 한 번에 만들지는 않았습니다.&lt;br /&gt;그다음에 한 일은 &lt;b&gt;작업 단위를 쪼개는 것&lt;/b&gt;이었습니다.&lt;/p&gt;
&lt;p data-end=&quot;2799&quot; data-start=&quot;2726&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2824&quot; data-start=&quot;2801&quot; data-ke-size=&quot;size16&quot;&gt;많은 사람들이 여기서 한 번 더 막힙니다.&lt;/p&gt;
&lt;p data-end=&quot;2932&quot; data-start=&quot;2826&quot; data-ke-size=&quot;size16&quot;&gt;자기소개, 프로젝트 설명, 문제 해결 사례, 협업 방식, 회고까지&lt;br /&gt;전부 한 번에 넣고 &amp;ldquo;포트폴리오 정리해줘&amp;rdquo;라고 하면&lt;br /&gt;AI는 겉보기에는 많이 만들어주는 것 같지만 실제로는 흐려집니다.&lt;/p&gt;
&lt;p data-end=&quot;2932&quot; data-start=&quot;2826&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2992&quot; data-start=&quot;2934&quot; data-ke-size=&quot;size16&quot;&gt;앞에서 강조한 강점이 뒤에서 사라지고,&lt;br /&gt;프로젝트 설명은 따로 놀고,&lt;br /&gt;문서 전체의 톤도 흔들립니다.&lt;/p&gt;
&lt;p data-end=&quot;2992&quot; data-start=&quot;2934&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3051&quot; data-start=&quot;2994&quot; data-ke-size=&quot;size16&quot;&gt;이건 AI가 멍청해서가 아닙니다.&lt;br /&gt;처리해야 할 맥락이 너무 많아지면 우선순위가 흔들리기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;3072&quot; data-start=&quot;3053&quot; data-ke-size=&quot;size16&quot;&gt;그래서 작업을 항목별로 나눴습니다.&lt;/p&gt;
&lt;p data-end=&quot;3159&quot; data-start=&quot;3074&quot; data-ke-size=&quot;size16&quot;&gt;자기소개는 자기소개대로,&lt;br /&gt;프로젝트 설명은 프로젝트 설명대로,&lt;br /&gt;강점 문장은 강점 문장대로,&lt;br /&gt;각 항목마다 필요한 자료와 브리핑만 따로 붙였습니다.&lt;/p&gt;
&lt;p data-end=&quot;3159&quot; data-start=&quot;3074&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3177&quot; data-start=&quot;3161&quot; data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 분명합니다.&lt;/p&gt;
&lt;p data-end=&quot;3291&quot; data-start=&quot;3179&quot; data-ke-size=&quot;size16&quot;&gt;전체를 한 번에 던질 때보다,&lt;br /&gt;AI가 지금 무엇에 집중해야 하는지가 선명해집니다.&lt;/p&gt;
&lt;p data-end=&quot;3291&quot; data-start=&quot;3179&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;문장의 밀도가 올라가고, 수정도 쉬워집니다.&lt;br /&gt;무엇보다 &lt;b&gt;왜 이 문장이 나왔는지 추적할 수 있게 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;3318&quot; data-start=&quot;3293&quot; data-ke-size=&quot;size16&quot;&gt;세션 마지막에 나온 반응도 그 지점이었습니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;3387&quot; data-start=&quot;3320&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;3387&quot; data-start=&quot;3322&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;더 세부적으로 나눠서 정리해야겠다는 걸 느꼈어요.&amp;rdquo;&lt;br /&gt;&amp;ldquo;이렇게 나눠서 하는 게 맞는 방향이라는 걸 알겠어요.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;3456&quot; data-start=&quot;3389&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3456&quot; data-start=&quot;3389&quot; data-ke-size=&quot;size16&quot;&gt;중요한 건 AI가 많이 만들어주는 것이 아닙니다.&lt;br /&gt;&lt;b&gt;사람이 통제할 수 있는 단위로 작업이 분해되어 있느냐&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-end=&quot;3461&quot; data-start=&quot;3458&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3490&quot; data-start=&quot;3463&quot; data-ke-size=&quot;size26&quot;&gt;한 모델이 만든 초안을 다른 모델로 검증했다&lt;/h2&gt;
&lt;p data-end=&quot;3531&quot; data-start=&quot;3492&quot; data-ke-size=&quot;size16&quot;&gt;초안이 나왔다고 끝이 아니었습니다.&lt;br /&gt;오히려 그때부터가 중요했습니다.&lt;/p&gt;
&lt;p data-end=&quot;3610&quot; data-start=&quot;3533&quot; data-ke-size=&quot;size16&quot;&gt;많은 사람이 AI 결과물을 받으면 그걸 거의 완성본처럼 취급합니다.&lt;/p&gt;
&lt;p data-end=&quot;3610&quot; data-start=&quot;3533&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하지만 실제로는 그 초안 안에도 구멍이 남아 있는 경우가 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;3640&quot; data-start=&quot;3612&quot; data-ke-size=&quot;size16&quot;&gt;그래서 같은 내용을 다른 모델로 다시 검토했습니다.&lt;/p&gt;
&lt;p data-end=&quot;3667&quot; data-start=&quot;3642&quot; data-ke-size=&quot;size16&quot;&gt;이 과정에서 꽤 자주 나오는 문제가 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3667&quot; data-start=&quot;3642&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3683&quot; data-start=&quot;3669&quot; data-ke-size=&quot;size16&quot;&gt;예를 들면 이런 식입니다.&lt;/p&gt;
&lt;p data-end=&quot;3755&quot; data-start=&quot;3685&quot; data-ke-size=&quot;size16&quot;&gt;자기소개 문단에서는 도메인 경험을 핵심 강점으로 세웠는데,&lt;br /&gt;프로젝트 설명 파트로 가면 그 강점이 전혀 이어지지 않는 경우.&lt;/p&gt;
&lt;p data-end=&quot;3809&quot; data-start=&quot;3757&quot; data-ke-size=&quot;size16&quot;&gt;혹은 지원 포지션은 백엔드인데,&lt;br /&gt;문서 전체 톤이 너무 기획자 서사처럼 정리되어 있는 경우.&lt;/p&gt;
&lt;p data-end=&quot;3880&quot; data-start=&quot;3811&quot; data-ke-size=&quot;size16&quot;&gt;앞에서는 협업과 맥락 이해를 장점으로 잡아놓고,&lt;br /&gt;뒤에서는 성과를 개인 작업처럼만 서술해서 흐름이 끊기는 경우도 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3880&quot; data-start=&quot;3811&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3927&quot; data-start=&quot;3882&quot; data-ke-size=&quot;size16&quot;&gt;혼자 읽을 때는 잘 안 보입니다.&lt;br /&gt;문장 단위로는 다 멀쩡해 보이기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;4005&quot; data-start=&quot;3929&quot; data-ke-size=&quot;size16&quot;&gt;하지만 다른 모델로 교차검증하면 이런 구조적 불일치가 드러납니다.&lt;br /&gt;한 모델이 자연스럽게 넘긴 부분을, 다른 모델은 문제로 짚어냅니다.&lt;/p&gt;
&lt;p data-end=&quot;4005&quot; data-start=&quot;3929&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4121&quot; data-start=&quot;4007&quot; data-ke-size=&quot;size16&quot;&gt;이번에도 그랬습니다.&lt;br /&gt;초안 자체는 꽤 잘 나와 있었지만, 전체 맥락을 이어 보면 앞에서 세운 포지션이 뒤에서 약해지는 부분이 있었습니다.&lt;br /&gt;그 피드백을 반영해 다시 다듬자 문서가 훨씬 단단해졌습니다.&lt;/p&gt;
&lt;p data-end=&quot;4199&quot; data-start=&quot;4123&quot; data-ke-size=&quot;size16&quot;&gt;AI를 잘 쓰는 사람은 보통 한 모델의 첫 결과를 그대로 믿지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;4199&quot; data-start=&quot;4123&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;초안을 만들 모델과, 구멍을 찾을 모델을 분리합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;4221&quot; data-start=&quot;4201&quot; data-ke-size=&quot;size16&quot;&gt;그 차이가 결과물의 밀도를 바꿉니다.&lt;/p&gt;
&lt;hr data-end=&quot;4226&quot; data-start=&quot;4223&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;4249&quot; data-start=&quot;4228&quot; data-ke-size=&quot;size26&quot;&gt;마지막에 가장 중요한 걸 확인했다&lt;/h2&gt;
&lt;p data-end=&quot;4289&quot; data-start=&quot;4251&quot; data-ke-size=&quot;size16&quot;&gt;작업이 거의 마무리됐을 때, 마지막으로 한 가지를 분명히 짚었습니다.&lt;/p&gt;
&lt;p data-end=&quot;4322&quot; data-start=&quot;4291&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이해하지 못한 문장은 포트폴리오에 넣지 않는 것.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;4322&quot; data-start=&quot;4291&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4338&quot; data-start=&quot;4324&quot; data-ke-size=&quot;size16&quot;&gt;이건 생각보다 중요합니다.&lt;/p&gt;
&lt;p data-end=&quot;4366&quot; data-start=&quot;4340&quot; data-ke-size=&quot;size16&quot;&gt;포트폴리오를 제출하면 결국 질문을 받게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;4434&quot; data-start=&quot;4368&quot; data-ke-size=&quot;size16&quot;&gt;왜 이렇게 구성했는지,&lt;br /&gt;이 판단은 어떤 경험에서 나온 건지,&lt;br /&gt;이 프로젝트에서 본인이 실제로 한 역할은 무엇인지.&lt;/p&gt;
&lt;p data-end=&quot;4497&quot; data-start=&quot;4436&quot; data-ke-size=&quot;size16&quot;&gt;그 질문에 자기 말로 답할 수 없다면,&lt;br /&gt;그건 포트폴리오가 아니라 &lt;b&gt;AI가 정리해준 문서&lt;/b&gt;에 가깝습니다.&lt;/p&gt;
&lt;p data-end=&quot;4497&quot; data-start=&quot;4436&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4553&quot; data-start=&quot;4499&quot; data-ke-size=&quot;size16&quot;&gt;AI는 구조를 제안할 수 있고,&lt;br /&gt;문장을 다듬을 수 있고,&lt;br /&gt;빠진 부분을 짚어줄 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;4614&quot; data-start=&quot;4555&quot; data-ke-size=&quot;size16&quot;&gt;하지만 그 문장을 이해하고,&lt;br /&gt;설명 가능하게 만들고,&lt;br /&gt;내 경험으로 다시 소화하는 건 사람의 일입니다.&lt;/p&gt;
&lt;p data-end=&quot;4614&quot; data-start=&quot;4555&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4682&quot; data-start=&quot;4616&quot; data-ke-size=&quot;size16&quot;&gt;이 지점에서 잠깐 멈칫하는 반응이 나왔습니다.&lt;br /&gt;AI가 정리해준 표현을 그대로 넣으려 했던 부분이 있었다고 했습니다.&lt;/p&gt;
&lt;p data-end=&quot;4698&quot; data-start=&quot;4684&quot; data-ke-size=&quot;size16&quot;&gt;그래서 다시 확인했습니다.&lt;/p&gt;
&lt;p data-end=&quot;4732&quot; data-start=&quot;4700&quot; data-ke-size=&quot;size16&quot;&gt;설명할 수 없는 건 넣지 않는다.&lt;br /&gt;이해한 것만 넣는다.&lt;/p&gt;
&lt;p data-end=&quot;4766&quot; data-start=&quot;4734&quot; data-ke-size=&quot;size16&quot;&gt;이 원칙이 있어야, AI를 써도 결과물이 내 것이 됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;4771&quot; data-start=&quot;4768&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;4793&quot; data-start=&quot;4773&quot; data-ke-size=&quot;size26&quot;&gt;세션이 끝난 뒤 남아야 하는 것&lt;/h2&gt;
&lt;p data-end=&quot;4827&quot; data-start=&quot;4795&quot; data-ke-size=&quot;size16&quot;&gt;이 작업은 한 번의 문장 첨삭으로 끝나는 종류가 아닙니다.&lt;/p&gt;
&lt;p data-end=&quot;4875&quot; data-start=&quot;4829&quot; data-ke-size=&quot;size16&quot;&gt;브리핑 설계,&lt;br /&gt;작업 단위 분해,&lt;br /&gt;초안 생성,&lt;br /&gt;교차검증,&lt;br /&gt;최종 자산화.&lt;/p&gt;
&lt;p data-end=&quot;4875&quot; data-start=&quot;4829&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4903&quot; data-start=&quot;4877&quot; data-ke-size=&quot;size16&quot;&gt;이 과정을 한 번 경험하면 중요한 게 남습니다.&lt;/p&gt;
&lt;p data-end=&quot;4957&quot; data-start=&quot;4905&quot; data-ke-size=&quot;size16&quot;&gt;문서 하나가 완성되는 것보다,&lt;br /&gt;&lt;b&gt;다음 작업에도 반복해서 쓸 수 있는 방식&lt;/b&gt;이 남습니다.&lt;/p&gt;
&lt;p data-end=&quot;4957&quot; data-start=&quot;4905&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5031&quot; data-start=&quot;4959&quot; data-ke-size=&quot;size16&quot;&gt;브리핑 템플릿,&lt;br /&gt;작업 단위를 나누는 기준,&lt;br /&gt;모델 간 교차검증 프롬프트,&lt;br /&gt;초안을 이해 가능한 문장으로 다시 바꾸는 기준.&lt;/p&gt;
&lt;p data-end=&quot;5078&quot; data-start=&quot;5033&quot; data-ke-size=&quot;size16&quot;&gt;이것들이 남아야 다음 포트폴리오도, 다음 프로젝트 정리도 혼자 돌릴 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;5078&quot; data-start=&quot;5033&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5134&quot; data-start=&quot;5080&quot; data-ke-size=&quot;size16&quot;&gt;제가 만들고 싶은 건 결과물 한 장이 아닙니다.&lt;br /&gt;&lt;b&gt;결과물이 계속 나오게 하는 구조&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-end=&quot;5139&quot; data-start=&quot;5136&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;5178&quot; data-start=&quot;5141&quot; data-ke-size=&quot;size26&quot;&gt;포트폴리오가 없는 게 아니라, 아직 제대로 넘기지 않은 것이다&lt;/h2&gt;
&lt;p data-end=&quot;5209&quot; data-start=&quot;5180&quot; data-ke-size=&quot;size16&quot;&gt;많은 사람들이 AI를 쓰고도 같은 자리에서 맴돕니다.&lt;/p&gt;
&lt;p data-end=&quot;5279&quot; data-start=&quot;5211&quot; data-ke-size=&quot;size16&quot;&gt;초안은 나왔는데 정리가 안 되고,&lt;br /&gt;정리는 했는데 내 것 같지 않고,&lt;br /&gt;다듬으려고 하면 처음부터 다시 시작하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;5304&quot; data-start=&quot;5281&quot; data-ke-size=&quot;size16&quot;&gt;이때 필요한 건 더 새로운 툴이 아닙니다.&lt;/p&gt;
&lt;p data-end=&quot;5304&quot; data-start=&quot;5281&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5372&quot; data-start=&quot;5306&quot; data-ke-size=&quot;size16&quot;&gt;브리핑을 갖추는 것,&lt;br /&gt;작업 단위를 쪼개는 것,&lt;br /&gt;교차검증으로 구멍을 찾는 것,&lt;br /&gt;그리고 이해한 것만 남기는 것.&lt;/p&gt;
&lt;p data-end=&quot;5372&quot; data-start=&quot;5306&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5421&quot; data-start=&quot;5374&quot; data-ke-size=&quot;size16&quot;&gt;이 순서를 아는 사람과 모르는 사람은&lt;br /&gt;같은 AI를 써도 결과물에서 차이가 납니다.&lt;/p&gt;
&lt;p data-end=&quot;5491&quot; data-start=&quot;5423&quot; data-ke-size=&quot;size16&quot;&gt;포트폴리오가 없는 게 아닐 수 있습니다.&lt;br /&gt;이미 해본 일은 있는데, 아직 &lt;b&gt;제대로 넘기지 못한 상태&lt;/b&gt;일 수 있습니다.&lt;/p&gt;
&lt;hr data-end=&quot;5496&quot; data-start=&quot;5493&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;5506&quot; data-start=&quot;5498&quot; data-ke-size=&quot;size26&quot;&gt;마지막으로&lt;/h2&gt;
&lt;p data-end=&quot;5605&quot; data-start=&quot;5508&quot; data-ke-size=&quot;size16&quot;&gt;AI를 이미 쓰고 있는데 결과물이 자꾸 붕 뜨는 분,&lt;br /&gt;만든 건 있는데 포트폴리오 문서로 정리가 안 되는 분,&lt;br /&gt;초안은 나오지만 면접에서 내 말로 설명할 자신이 없는 분.&lt;/p&gt;
&lt;p data-end=&quot;5605&quot; data-start=&quot;5508&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5649&quot; data-start=&quot;5607&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Portfolio Structure&lt;/b&gt;는 4회 1:1 온라인 세션입니다.&lt;/p&gt;
&lt;p data-end=&quot;5704&quot; data-start=&quot;5651&quot; data-ke-size=&quot;size16&quot;&gt;브리핑 설계부터 단위 분해, 교차검증, 최종 정리까지&lt;br /&gt;실제 작업물을 가지고 같이 진행합니다.&lt;/p&gt;
&lt;p data-end=&quot;5704&quot; data-start=&quot;5651&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5744&quot; data-start=&quot;5706&quot; data-ke-size=&quot;size16&quot;&gt;세션이 끝났을 때 남아야 하는 건&lt;br /&gt;포트폴리오 한 건만이 아닙니다.&lt;/p&gt;
&lt;p data-end=&quot;5780&quot; data-start=&quot;5746&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음 작업도 혼자 돌릴 수 있는 방식&lt;/b&gt;이 남아야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;5780&quot; data-start=&quot;5746&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5848&quot; data-start=&quot;5782&quot; data-ke-size=&quot;size16&quot;&gt;현재 파일럿 케이스를 소수 모집 중입니다.&lt;br /&gt;아래 폼에 현재 상황만 남겨주시면 검토 후 세부 안내를 메일로 드립니다.&lt;/p&gt;
&lt;p data-end=&quot;5884&quot; data-start=&quot;5850&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a data-end=&quot;5882&quot; data-start=&quot;5852&quot;&gt;Portfolio Structure 신청하기 &amp;rarr;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;5884&quot; data-start=&quot;5850&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;5884&quot; data-start=&quot;5850&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;관련글&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1774223533704&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;쓸모없어 보이던 경력을 AI로 번역해봤다&quot; data-og-description=&quot;막막한 사람에게 지도를 그려주는 건 전문가가 아닙니다.막막함 자체를 구조화하는 과정이 지도를 만듭니다. 부트캠프를 듣고 있는데도,막상 지원하려 하면 멈추는 사람들이 있습니다. 기술이 &quot; data-og-host=&quot;chessire.tistory.com&quot; data-og-source-url=&quot;https://chessire.tistory.com/entry/career-translation-with-ai&quot; data-og-url=&quot;https://chessire.tistory.com/entry/career-translation-with-ai&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/RP2uU/dJMb8QelyKR/VQklcW38eyZPRIj2e7ubAK/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/cJCAqI/dJMb8WMoVSM/y8l5aTyVWRakxUrQAqPAok/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/b1vsEh/dJMb8RRReXj/knBqoIC1w04tl67NxkQsO1/img.png?width=1024&amp;amp;height=559&amp;amp;face=0_0_1024_559&quot;&gt;&lt;a href=&quot;https://chessire.tistory.com/entry/career-translation-with-ai&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chessire.tistory.com/entry/career-translation-with-ai&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/RP2uU/dJMb8QelyKR/VQklcW38eyZPRIj2e7ubAK/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/cJCAqI/dJMb8WMoVSM/y8l5aTyVWRakxUrQAqPAok/img.png?width=800&amp;amp;height=436&amp;amp;face=0_0_800_436,https://scrap.kakaocdn.net/dn/b1vsEh/dJMb8RRReXj/knBqoIC1w04tl67NxkQsO1/img.png?width=1024&amp;amp;height=559&amp;amp;face=0_0_1024_559');&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;쓸모없어 보이던 경력을 AI로 번역해봤다&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;막막한 사람에게 지도를 그려주는 건 전문가가 아닙니다.막막함 자체를 구조화하는 과정이 지도를 만듭니다. 부트캠프를 듣고 있는데도,막상 지원하려 하면 멈추는 사람들이 있습니다. 기술이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chessire.tistory.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;</description>
      <category>AI/AI 활용</category>
      <category>ai워크플로우</category>
      <category>AI컨설팅</category>
      <category>ai활용</category>
      <category>워크플로우설계</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/119</guid>
      <comments>https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow#entry119comment</comments>
      <pubDate>Mon, 23 Mar 2026 04:33:09 +0900</pubDate>
    </item>
    <item>
      <title>쓸모없어 보이던 경력을 AI로 번역해봤다</title>
      <link>https://chessire.tistory.com/entry/career-translation-with-ai</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;막막한 사람에게 지도를 그려주는 건 전문가가 아닙니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;막막함 자체를 구조화하는 과정이 지도를 만듭니다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ubkUN/dJMcabDs9XF/T0OhmTxRSuuskFacabDmH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ubkUN/dJMcabDs9XF/T0OhmTxRSuuskFacabDmH1/img.png&quot; data-alt=&quot;AI를 통한 경험 번역&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ubkUN/dJMcabDs9XF/T0OhmTxRSuuskFacabDmH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FubkUN%2FdJMcabDs9XF%2FT0OhmTxRSuuskFacabDmH1%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;1024&quot; height=&quot;559&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AI를 통한 경험 번역&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;막상 지원하려 하면 멈추는 사람들이 있습니다.&lt;/p&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;최근 그런 상태의 수강생과 1시간짜리 세션을 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겉으로 보면 평범한 직무 전환 케이스였습니다. 수강 중, 결과물은 애매하고, 어떤 직무를 목표로 해야 할지도 불분명한 상태. 그런데 이 케이스의 핵심은 기술 수준이 아니었습니다. &lt;b&gt;문제는 이미 가진 경험이 채용 시장에서 읽히는 언어로 번역되지 않고 있다는 점&lt;/b&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;없던 경력이 생긴 게 아닙니다. 원래 있던 경험이, 이제야 지원 가능한 형태로 보이기 시작한 겁니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제는 공부량이 아니라 구조 부재였다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 수강생의 상태를 겉으로만 보면 흔히 이렇게 해석하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;실력이 부족한가 보다. 더 공부해야겠네.&quot; 하지만 실제로는 그게 아니었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 해의 실무 경험이 있었습니다.&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;어떤 방향으로 번역해야 면접에서 살아나는지.&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;더 많이 배우게 하는 것이 아니라, &lt;b&gt;이미 가진 경험을 실행 가능한 방향으로 구조화하는 것.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI를 써서 막막함을 실행 계획으로 바꿨다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 전 상태는 이랬습니다. 가고 싶은 방향조차 없었지습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 직무 전환 사례였지만, 본질은 특정 직군의 문제가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람이 비슷한 방식으로 자기 경험을 설명하지 못해 멈춥니다.&lt;/p&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;기존 결과물을 재정리할지 새로 만들지 A/B로 판단했으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만들 경우 어떤 주제로 어디까지 만들어야 하는지까지 내려왔습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;AI를 통해 막연한 &quot;이쪽으로 가고 싶다&quot;가 생겼고,&lt;br /&gt;그 이후에는 지원 전략과 실행 계획까지 붙은 셈입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 만드는 데 쓴 방식은 단순했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 경력 데이터를 AI에게 넣어 &lt;b&gt;강점 영역과 지원 가능한 도메인을 분석&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수강생 본인도 처음 보는 자기 분석 결과였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오래 다뤄온 실무 경험이, 특정 회사군에서 오히려 유리한 포지션이 될 수 있다는 방향이 나왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 그 결과를 &lt;b&gt;지원 전략 문서로 정리&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 포지션, 결과물 방향, 목표 시점까지의 타임라인.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대화로 끝나는 것이 아니라 다음에 꺼낼 수 있는 형태로 저장했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 문서를 &lt;b&gt;다른 AI에게 넘겨 현실성을 검증&lt;/b&gt;했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 내용을 서로 다른 AI에게 보여주면 보는 각도가 달라집니다.&lt;/p&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;&quot;범위가 주어진 기간 대비 넓다&quot;는 피드백이 나왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 만들어진 계획이 다소 이상적이었던 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 피드백을 다시 반영해 &lt;b&gt;범위를 줄이고 실행 계획으로 바꿨습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로 A안과 B안, 두 가지 선택지가 나왔고, 수강생이 직접 하나를 골랐습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI가 해준 건 '결정'이 아니라 '번역'이었다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 걸 짚어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 AI를 여러 번 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 핵심은 &quot;AI를 몇 개 썼는가&quot;가 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 해준 것은 흩어진 경력을 정리하고,&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;blockquote data-ke-style=&quot;style2&quot;&gt;즉 사람이 이미 갖고 있던 경험을, 채용 시장에서 읽히는 언어로 다시 정렬해준 것입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경력은 있었지만 경력처럼 보이지 않았고,&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;AI는 바로 그 중간 번역기를 해줬습니다.&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;그 비용의 상당 부분은 &quot;경험을 언어로 번역하는 과정&quot;에 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 과정을, 지금은 AI로 훨씬 빠르게 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 AI가 모든 걸 대신해주진 않습니다.&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;blockquote data-ke-style=&quot;style2&quot;&gt;AI를 잘 쓰는 사람은 AI에게 결정을 떠넘기는 사람이 아닙니다.&lt;br /&gt;&lt;b&gt;AI를 이용해 판단 가능한 상태를 만드는 사람&lt;/b&gt;입니다.&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;진짜 지표는 '열정'이 아니라 다음 행동이다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 마지막에 수강생이 이렇게 말했습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;열정이 생겨요.&quot;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 반응입니다.&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;A안과 B안 중 무엇을 선택했는지,&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;&quot;어디서부터 시작해야 할지 모르겠다&quot;는 상태와,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;다음 주까지 뭘 해야 할지 알겠다&quot;는 상태는 완전히 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취업 준비에서 가장 무서운 건 느리게 가는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아무 방향도 없는 채로 같은 자리를 계속 맴도는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방향이 생기면 속도는 나중 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방향이 없으면 속도는 아예 의미가 없습니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;없는 경력을 만드는 게 아니라, 있는 경험을 다시 보이게 하는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람들이 정말로 경력이 없어서 막히는 게 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 가진 경험이 있는데,&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;현업과의 소통 경험은 협업 역량이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경력의 가치가 갑자기 새로 생긴 게 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 있던 가치가 제대로 읽히기 시작한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 사례는 특정 직무 전환 케이스였지만,&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;이미 있는 것을 지원 가능한 형태로 다시 쓰는 일.&lt;/p&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;&quot;나는 아무것도 없다&quot;에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;아, 내가 가진 걸 이렇게 쓸 수 있구나&quot;로 넘어가기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람들에게 필요한 건 더 많은 정보가 아니라,&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;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마지막으로&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내 경력도 번역이 되는지 확인해보고 싶다면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;아래 폼에 현재 상황만 남겨주세요. 검토 후 세부 안내를 메일로 드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://forms.gle/6KBCqL13CDBtvEk8A&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Career Translate 신청하기 &amp;rarr;]&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비슷한 글&lt;/h2&gt;
&lt;figure id=&quot;og_1773641654646&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;AI로 블로그 3개월, PV 86% 오른 이야기&quot; data-og-description=&quot;기술 블로그를AI로 운영한 3개월그리고 솔직한 숫자시간을 줄이면 퀄리티가 떨어진다고 생각했습니다.아니었습니다.마케터도 작가도 아닌데 AI 관련 영상이나 글을 보면 다들 쉽게 되는 것처럼 &quot; data-og-host=&quot;chessire.tistory.com&quot; data-og-source-url=&quot;https://chessire.tistory.com/entry/ai-blog-3month-result&quot; data-og-url=&quot;https://chessire.tistory.com/entry/ai-blog-3month-result&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dO1mM6/dJMb9fZt5pI/y3gR9sIkkE4LzKmwIT0Gm0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cIhxon/dJMb9jgvYjn/M0eDHZ5EqfAokbE8jMFQJ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/boop01/dJMb9hCZ367/OdO0kewV8nY3TNheLko3sk/img.png?width=889&amp;amp;height=392&amp;amp;face=0_0_889_392&quot;&gt;&lt;a href=&quot;https://chessire.tistory.com/entry/ai-blog-3month-result&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chessire.tistory.com/entry/ai-blog-3month-result&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dO1mM6/dJMb9fZt5pI/y3gR9sIkkE4LzKmwIT0Gm0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cIhxon/dJMb9jgvYjn/M0eDHZ5EqfAokbE8jMFQJ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/boop01/dJMb9hCZ367/OdO0kewV8nY3TNheLko3sk/img.png?width=889&amp;amp;height=392&amp;amp;face=0_0_889_392');&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;AI로 블로그 3개월, PV 86% 오른 이야기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;기술 블로그를AI로 운영한 3개월그리고 솔직한 숫자시간을 줄이면 퀄리티가 떨어진다고 생각했습니다.아니었습니다.마케터도 작가도 아닌데 AI 관련 영상이나 글을 보면 다들 쉽게 되는 것처럼&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chessire.tistory.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;figure id=&quot;og_1774223554702&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;AI를 쓰는데도 포트폴리오가 안 나오는 이유&quot; data-og-description=&quot;도구가 없어서 막히는 게 아닙니다.넘기는 방식이 틀려서 막히는 겁니다.이미 ChatGPT도 써봤고, Claude도 써봤고, 결과물도 몇 번 뽑아봤습니다.그런데 이상하게 포트폴리오는 잘 안 나옵니다. 초&quot; data-og-host=&quot;chessire.tistory.com&quot; data-og-source-url=&quot;https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow&quot; data-og-url=&quot;https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Im4jc/dJMb9c9xc5l/lZg88an3biMsISSlKBpGPk/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/sZOk6/dJMb9lMaSIy/Dz2OuDMrZP35aKoRaVic10/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/eNzUE/dJMb9frEOY8/9ZQeGmCbfES7y6BB9L0d61/img.png?width=1376&amp;amp;height=768&amp;amp;face=0_0_1376_768&quot;&gt;&lt;a href=&quot;https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chessire.tistory.com/entry/ai-portfolio-briefing-workflow&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Im4jc/dJMb9c9xc5l/lZg88an3biMsISSlKBpGPk/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/sZOk6/dJMb9lMaSIy/Dz2OuDMrZP35aKoRaVic10/img.png?width=800&amp;amp;height=446&amp;amp;face=0_0_800_446,https://scrap.kakaocdn.net/dn/eNzUE/dJMb9frEOY8/9ZQeGmCbfES7y6BB9L0d61/img.png?width=1376&amp;amp;height=768&amp;amp;face=0_0_1376_768');&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;AI를 쓰는데도 포트폴리오가 안 나오는 이유&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;도구가 없어서 막히는 게 아닙니다.넘기는 방식이 틀려서 막히는 겁니다.이미 ChatGPT도 써봤고, Claude도 써봤고, 결과물도 몇 번 뽑아봤습니다.그런데 이상하게 포트폴리오는 잘 안 나옵니다. 초&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chessire.tistory.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;</description>
      <category>AI/AI 활용</category>
      <category>ai활용</category>
      <category>경력번역</category>
      <category>이직준비</category>
      <category>직무전환</category>
      <category>직업훈련</category>
      <category>취업준비</category>
      <category>커리어</category>
      <category>커리어컨설팅</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/117</guid>
      <comments>https://chessire.tistory.com/entry/career-translation-with-ai#entry117comment</comments>
      <pubDate>Mon, 16 Mar 2026 14:02:09 +0900</pubDate>
    </item>
    <item>
      <title>디지털 트윈: 시각적 구현을 넘어 데이터 생산 시스템으로</title>
      <link>https://chessire.tistory.com/entry/digital-twin-layers</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BN0wg/dJMcacB8GUf/grjZbQczLrU3jKSPrbRCE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BN0wg/dJMcacB8GUf/grjZbQczLrU3jKSPrbRCE0/img.png&quot; data-alt=&quot;Digital Twin Layers&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BN0wg/dJMcacB8GUf/grjZbQczLrU3jKSPrbRCE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBN0wg%2FdJMcacB8GUf%2FgrjZbQczLrU3jKSPrbRCE0%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;520&quot; height=&quot;284&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;559&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Digital Twin Layers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;2106&quot; data-start=&quot;1916&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2106&quot; data-start=&quot;1916&quot; data-ke-size=&quot;size16&quot;&gt;실시간 시뮬레이션에서 가장 먼저 흔들리는 축은 물리 현상보다 &lt;b&gt;시간&lt;/b&gt;인 경우가 많습니다. 시간이 흔들리면 데이터의 선후 관계가 흐려지고, 이는 시스템 신뢰도 저하로 직결됩니다. 본 글은 화려한 월드 구성보다 &lt;b&gt;오차 발산을 제어하는 시간 모델&lt;/b&gt;을 최우선 전제로 두고, 각 레이어를 데이터 생산 관점으로 정렬하는 설계 관점을 정리합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;2142&quot; data-start=&quot;2108&quot; data-ke-size=&quot;size26&quot;&gt;0. 근본 전제: 오차 발산을 제어하는 시간 모델&lt;/h2&gt;
&lt;p data-end=&quot;2223&quot; data-start=&quot;2143&quot; data-ke-size=&quot;size16&quot;&gt;초기 설계에서는 엔진 기본 Tick에 의존하기 쉽습니다. 그러나 프레임레이트 변동성은 누적 오차를 만드는 주요 요인이며, 재현성을 떨어뜨립니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2386&quot; data-start=&quot;2225&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2281&quot; data-start=&quot;2225&quot;&gt;프레임 기반(Variable Step): 환경에 따라 불안정하며 재현성이 확보되기 어렵습니다.&lt;/li&gt;
&lt;li data-end=&quot;2386&quot; data-start=&quot;2282&quot;&gt;고정/통제된 시간 모델(Controlled Timestep): 설계 난도는 높지만 수치적 안정성을 확보할 수 있으며, 장기 실행에서도 결과 발산을 억제하는 검증 가능한 기반이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2436&quot; data-start=&quot;2388&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;h2 data-end=&quot;2477&quot; data-start=&quot;2438&quot; data-ke-size=&quot;size26&quot;&gt;1. 월드 레이어: 시각적 재현이 아닌 측정 가능한 좌표계&lt;/h2&gt;
&lt;p data-end=&quot;2522&quot; data-start=&quot;2478&quot; data-ke-size=&quot;size16&quot;&gt;월드는 배경이 아니라 &lt;b&gt;기준 레퍼런스(Reference Frame)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2708&quot; data-start=&quot;2524&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2599&quot; data-start=&quot;2524&quot;&gt;정밀도 우선: 외부 스캔/지도 데이터를 이식할 때 좌표계와 스케일의 일관성이 무너지면 센서 데이터의 물리적 설명력이 약해집니다.&lt;/li&gt;
&lt;li data-end=&quot;2708&quot; data-start=&quot;2600&quot;&gt;표준화: 원점, 축 방향, 단위를 명확히 규정하여 월드의 퀄리티가 아니라 &lt;b&gt;측정의 정밀도&lt;/b&gt;에 집중합니다. 이를 통해 센서 레이어가 단순 렌더링이 아닌 계측 단계로 진입할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;2763&quot; data-start=&quot;2710&quot; data-ke-size=&quot;size26&quot;&gt;2. 센서 레이어: 화면 출력이 아닌 측정 장치(Measurement Device)&lt;/h2&gt;
&lt;p data-end=&quot;2817&quot; data-start=&quot;2764&quot; data-ke-size=&quot;size16&quot;&gt;센서는 시각적 결과물이 아니라, 정의된 규칙에 따라 데이터를 추출하는 측정기로 취급해야 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3010&quot; data-start=&quot;2819&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2896&quot; data-start=&quot;2819&quot;&gt;모델링 분리: 카메라, LiDAR 센서를 구현할 때 렌더링 파이프라인과 물리적 측정 규칙(필터, 노이즈, 왜곡 모델)을 분리합니다.&lt;/li&gt;
&lt;li data-end=&quot;3010&quot; data-start=&quot;2897&quot;&gt;인사이트: 그럴듯한 이미지를 생성하는 것보다, 데이터 생성 조건(Time-stamp, Noise Model)이 명확해야 검증 가능성이 확보됩니다. 조건이 불명확하면 재현성과 검증 가능성이 떨어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;3045&quot; data-start=&quot;3012&quot; data-ke-size=&quot;size26&quot;&gt;3. 에이전트 레이어: 알고리즘과 동역학의 분리&lt;/h2&gt;
&lt;p data-end=&quot;3110&quot; data-start=&quot;3046&quot; data-ke-size=&quot;size16&quot;&gt;에이전트의 움직임을 구현할 때 경로 계획(Algorithm)과 물리적 거동(Dynamics)을 분리하여 설계합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3220&quot; data-start=&quot;3112&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3166&quot; data-start=&quot;3112&quot;&gt;디버깅 가시성: 의사결정의 문제인지, 제어 및 물리 모델의 한계인지를 구분할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;3220&quot; data-start=&quot;3167&quot;&gt;확장성: 알고리즘을 교체하더라도 물리적 신뢰성을 유지하며 트래픽 모델로 확장할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3281&quot; data-start=&quot;3222&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;h2 data-end=&quot;3317&quot; data-start=&quot;3283&quot; data-ke-size=&quot;size26&quot;&gt;4. 시스템 동역학 및 지연(Latency) 관리&lt;/h2&gt;
&lt;p data-end=&quot;3355&quot; data-start=&quot;3318&quot; data-ke-size=&quot;size16&quot;&gt;실시간 시뮬레이션에서 연산 자원과 정확도는 트레이드오프 관계입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3518&quot; data-start=&quot;3357&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3412&quot; data-start=&quot;3357&quot;&gt;최적화 전략: 실시간성을 유지하면서 수치해석적 정확도를 유지할 수 있는 임계점을 정의합니다.&lt;/li&gt;
&lt;li data-end=&quot;3518&quot; data-start=&quot;3413&quot;&gt;지연 모델링: 네트워크 송수신/하드웨어 제어에서 발생하는 지연이 인과율에 미치는 영향을 설계 단계에서 고려합니다. 지연이 반영되지 않으면 실제 환경 적용에서 오차가 확대될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;3564&quot; data-start=&quot;3520&quot; data-ke-size=&quot;size26&quot;&gt;5. 데이터 레이어: 재현 가능성과 추적성(Traceability)&lt;/h2&gt;
&lt;p data-end=&quot;3604&quot; data-start=&quot;3565&quot; data-ke-size=&quot;size16&quot;&gt;데이터의 가치는 양이 아니라 &lt;b&gt;수집 조건의 명확성&lt;/b&gt;에서 결정됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3711&quot; data-start=&quot;3606&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3655&quot; data-start=&quot;3606&quot;&gt;메타데이터 고정: 좌표계, 타임스탬프, 노이즈 규칙, 시나리오 ID를 결합합니다.&lt;/li&gt;
&lt;li data-end=&quot;3711&quot; data-start=&quot;3656&quot;&gt;구조화: 생성 데이터가 어떤 조건에서 도출되었는지 역추적 가능해야 데이터로서의 자격을 갖습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;3748&quot; data-start=&quot;3713&quot; data-ke-size=&quot;size26&quot;&gt;6. 송수신 레이어: 시스템 인터페이스의 경계 정의&lt;/h2&gt;
&lt;p data-end=&quot;3783&quot; data-start=&quot;3749&quot; data-ke-size=&quot;size16&quot;&gt;시뮬레이터는 단독 프로그램이 아니라 시스템의 구성 요소입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3899&quot; data-start=&quot;3785&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3849&quot; data-start=&quot;3785&quot;&gt;프로토콜 정리: TCP/UDP, gRPC, MQTT, CAN 등 통신 규격과 유실/동기화 규칙을 정의합니다.&lt;/li&gt;
&lt;li data-end=&quot;3899&quot; data-start=&quot;3850&quot;&gt;경계 정의: 입력과 출력의 경계가 잡혀야 검증 가능한 시스템으로 운영할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-end=&quot;3941&quot; data-start=&quot;3901&quot; data-ke-size=&quot;size26&quot;&gt;7. 검증 레이어: 폐쇄 루프(Closed-loop)의 완성&lt;/h2&gt;
&lt;p data-end=&quot;3974&quot; data-start=&quot;3942&quot; data-ke-size=&quot;size16&quot;&gt;검증이 없는 데이터 생산은 반복될수록 왜곡될 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;4102&quot; data-start=&quot;3976&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;4032&quot; data-start=&quot;3976&quot;&gt;재현성 테스트: 동일 조건에서 동일 결과가 도출되는지(Determinism)를 모니터링합니다.&lt;/li&gt;
&lt;li data-end=&quot;4102&quot; data-start=&quot;4033&quot;&gt;표준 준수: OpenDRIVE, OpenSCENARIO 등 표준 규격을 고려하고 시나리오 기반 엣지 케이스를 검증합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-end=&quot;4234&quot; data-start=&quot;4104&quot; data-ke-size=&quot;size16&quot;&gt;요약하면, 성공적인 디지털 트윈 시뮬레이션은 엔진 성능이 아니라 &lt;b&gt;오차가 발산하지 않는 시간 모델&lt;/b&gt; 위에서 각 레이어를 데이터 생산 관점으로 정렬하는 설계 역량에 달려 있습니다. 발산하지 않는 시스템만이 개선과 확장을 허용합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-end=&quot;862&quot; data-start=&quot;675&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;디지털 트윈은 단순한 구현을 넘어, 시간&amp;middot;센서&amp;middot;데이터&amp;middot;검증이 맞물리는 &lt;b&gt;공학적 설계 문제&lt;/b&gt;로 확장됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #456771;&quot;&gt;본 글의 7단계 레이어 설계(시간 모델&amp;rarr;월드&amp;rarr;센서&amp;rarr;에이전트&amp;rarr;지연&amp;rarr;데이터&amp;rarr;연동/검증)를 실제 프로젝트에 적용하거나, 현재 구조의 발산이나 비재현 이슈를 정리하고 싶다면 연락 주시면 됩니다. 멘토링 및 기술 자문도 열어두었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;916&quot; data-start=&quot;864&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;893&quot; data-start=&quot;864&quot;&gt;&lt;span style=&quot;color: #1a5490;&quot;&gt;Email: &lt;a style=&quot;color: #1a5490;&quot; data-end=&quot;891&quot; data-start=&quot;873&quot;&gt;chessire@naver.com&lt;span aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;916&quot; data-start=&quot;894&quot;&gt;&lt;a href=&quot;https://www.linkedin.com/in/gm-kim/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #1a5490;&quot;&gt;LinkedIn: DM(프로필 링크)&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Notes/Tech History</category>
      <category>Digital-twin</category>
      <category>LIDAR</category>
      <category>OpenDRIVE</category>
      <category>OpenSCENARIO</category>
      <category>ue5</category>
      <category>UnrealEngine</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/115</guid>
      <comments>https://chessire.tistory.com/entry/digital-twin-layers#entry115comment</comments>
      <pubDate>Mon, 16 Mar 2026 08:04:35 +0900</pubDate>
    </item>
    <item>
      <title>현대 CPU 최적화의 본질: 연산(ALU)이 아닌 메모리(LSU)</title>
      <link>https://chessire.tistory.com/entry/cpu-cache-locality-alignment-soa-aos</link>
      <description>&lt;blockquote data-end=&quot;99&quot; data-start=&quot;40&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; CPU는 연산보다&lt;br /&gt;데이터를 가져오는 방식에&lt;br /&gt;훨씬 민감하다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-end=&quot;298&quot; data-start=&quot;101&quot; data-ke-size=&quot;size16&quot;&gt;CPU 최적화를 연산을 줄이는 일로만 보면, 체감 성능이 잘 안 나옵니다. 실전 병목은 대개 계산(ALU)이 아니라 &lt;b&gt;메모리 접근(Load/Store)&lt;/b&gt;에서 터집니다. CPU는 load =&amp;gt; execute =&amp;gt; add 같은 일을 파이프라인으로 겹쳐서 처리할 수 있지만, &lt;b&gt;데이터가 제때 도착하지 않으면&lt;/b&gt; 실행 유닛은 그냥 놀게 됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;359&quot; data-start=&quot;356&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cypqi0/dJMcacWjefx/OPzcTKyeUkopV7xMoiweX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cypqi0/dJMcacWjefx/OPzcTKyeUkopV7xMoiweX1/img.png&quot; data-alt=&quot;LSU vs ALU&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cypqi0/dJMcacWjefx/OPzcTKyeUkopV7xMoiweX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcypqi0%2FdJMcacWjefx%2FOPzcTKyeUkopV7xMoiweX1%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;480&quot; height=&quot;480&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LSU vs ALU&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-end=&quot;409&quot; data-start=&quot;361&quot; data-ke-size=&quot;size26&quot;&gt;1) 패러다임 전환: 연산이 아니라 물류(Load/Store)가 문제다&lt;/h2&gt;
&lt;p data-end=&quot;430&quot; data-start=&quot;410&quot; data-ke-size=&quot;size16&quot;&gt;CPU 내부엔 역할 분리가 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;506&quot; data-start=&quot;432&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;475&quot; data-start=&quot;432&quot;&gt;&lt;b&gt;LSU(Load/Store Unit)&lt;/b&gt;: 메모리를 읽고/쓰는 담당&lt;/li&gt;
&lt;li data-end=&quot;506&quot; data-start=&quot;476&quot;&gt;&lt;b&gt;ALU/FPU/SIMD&lt;/b&gt;: 실제 계산 담당&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;552&quot; data-start=&quot;508&quot; data-ke-size=&quot;size16&quot;&gt;코드가 느릴 때 계산량이 많아서일 수도 있지만, 더 흔한 케이스는 이겁니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;633&quot; data-start=&quot;554&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;554&quot;&gt;계산은 준비됐는데 &lt;b&gt;로드가 늦어서 실행이 멈춘다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;633&quot; data-start=&quot;586&quot;&gt;실행 중에 다음 데이터를 추가로 로드하려다가 &lt;b&gt;캐시 미스&lt;/b&gt;로 브레이크가 걸린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;689&quot; data-start=&quot;635&quot; data-ke-size=&quot;size16&quot;&gt;그래서 최적화의 시작점은 연산 줄이기가 아니라 &lt;b&gt;캐시 히트율을 올리는 데이터 배치&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-end=&quot;694&quot; data-start=&quot;691&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;737&quot; data-start=&quot;696&quot; data-ke-size=&quot;size26&quot;&gt;2) 캐시의 작동 원리: CPU는 64B &amp;lsquo;박스&amp;rsquo; 단위로 움직인다&lt;/h2&gt;
&lt;p data-end=&quot;816&quot; data-start=&quot;738&quot; data-ke-size=&quot;size16&quot;&gt;캐시는 바이트 단위로 움직이지 않습니다. 보통 &lt;b&gt;캐시 라인(Cache Line)&lt;/b&gt; 단위(대부분 64B)를 최소 단위로 가져오고 버립니다.&lt;/p&gt;
&lt;p data-end=&quot;832&quot; data-start=&quot;818&quot; data-ke-size=&quot;size16&quot;&gt;여기서 지역성이 나옵니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;924&quot; data-start=&quot;834&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;878&quot; data-start=&quot;834&quot;&gt;&lt;b&gt;공간 지역성(Spatial)&lt;/b&gt;: 다음에 접근할 메모리가 인접해 있다.&lt;/li&gt;
&lt;li data-end=&quot;924&quot; data-start=&quot;879&quot;&gt;&lt;b&gt;시간 지역성(Temporal)&lt;/b&gt;: 방금 접근한 메모리를 곧 다시 쓴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;968&quot; data-start=&quot;926&quot; data-ke-size=&quot;size16&quot;&gt;즉, 우리가 코드를 예측 가능하게 만든다는 말의 실체는 대부분 이겁니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1056&quot; data-start=&quot;970&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;997&quot; data-start=&quot;970&quot;&gt;인접 데이터를 연속으로 쓰게 만들고(공간)&lt;/li&gt;
&lt;li data-end=&quot;1026&quot; data-start=&quot;998&quot;&gt;최근에 쓴 데이터를 다시 쓰게 만들면(시간)&lt;/li&gt;
&lt;li data-end=&quot;1056&quot; data-start=&quot;1027&quot;&gt;캐시 히트율이 올라가고, 로드 지연이 줄어듭니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1061&quot; data-start=&quot;1058&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1105&quot; data-start=&quot;1063&quot; data-ke-size=&quot;size26&quot;&gt;3) 예측 실패보다 무서운 설계 실수: 캐시 미스는 4C로 보자&lt;/h2&gt;
&lt;p data-end=&quot;1174&quot; data-start=&quot;1106&quot; data-ke-size=&quot;size16&quot;&gt;교과서적 분류는 3C(Cold/Capacity/Conflict)지만, 멀티코어까지 다루려면 &lt;b&gt;4C&lt;/b&gt;가 더 정합적입니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1195&quot; data-start=&quot;1176&quot; data-ke-size=&quot;size23&quot;&gt;4C Cache Miss&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1543&quot; data-start=&quot;1196&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1247&quot; data-start=&quot;1196&quot;&gt;&lt;b&gt;Cold (Compulsory) Miss&lt;/b&gt;&lt;br /&gt;처음 접근이라 캐시에 없어서 발생.&lt;/li&gt;
&lt;li data-end=&quot;1301&quot; data-start=&quot;1249&quot;&gt;&lt;b&gt;Capacity Miss&lt;/b&gt;&lt;br /&gt;캐시 용량 자체가 부족해서, 담아두지 못하고 밀려남.&lt;/li&gt;
&lt;li data-end=&quot;1415&quot; data-start=&quot;1303&quot;&gt;&lt;b&gt;Conflict Miss&lt;/b&gt;&lt;br /&gt;캐시에 공간은 있는데 매핑/세트 충돌 때문에 교체가 과하게 발생.&lt;br /&gt;특히 stride 패턴이 캐시 인덱스와 맞물리면 &lt;b&gt;계속 갈아엎는 현상&lt;/b&gt;이 나옵니다.&lt;/li&gt;
&lt;li data-end=&quot;1543&quot; data-start=&quot;1417&quot;&gt;&lt;b&gt;Coherency Miss (일관성 미스)&lt;/b&gt;&lt;br /&gt;다른 코어가 내가 들고 있던 캐시 라인을 수정해서 &lt;b&gt;Invalidate&lt;/b&gt;가 걸린 경우.&lt;br /&gt;이게 나중에 말할 &lt;b&gt;False Sharing&lt;/b&gt;의 바로 그 뿌리입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;1651&quot; data-start=&quot;1545&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요한 건, 미스를 예측 실패 하나로 뭉개면 원인 진단이 틀어진다는 점입니다.&lt;br /&gt;Capacity인지, Conflict인지, Coherency인지에 따라 처방이 완전히 달라집니다.&lt;/p&gt;
&lt;hr data-end=&quot;1656&quot; data-start=&quot;1653&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1697&quot; data-start=&quot;1658&quot; data-ke-size=&quot;size26&quot;&gt;4) Stride 프리패처: CPU는 일정 보폭을 좋아한다&lt;/h2&gt;
&lt;p data-end=&quot;1763&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size16&quot;&gt;하드웨어 프리패처는 다음 줄을 무조건 읽어오기만 하지 않습니다. &lt;b&gt;규칙적인 보폭(Stride)&lt;/b&gt;을 학습합니다.&lt;/p&gt;
&lt;p data-end=&quot;1771&quot; data-start=&quot;1765&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1841&quot; data-start=&quot;1773&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1841&quot; data-start=&quot;1773&quot;&gt;[0] -&amp;gt; [4] -&amp;gt; [8] -&amp;gt; [12] 처럼 일정하면&lt;br /&gt;&amp;rarr; 4칸씩 뛴다는 점을 학습하고 미리 끌어옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1847&quot; data-start=&quot;1843&quot; data-ke-size=&quot;size16&quot;&gt;반대로,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1937&quot; data-start=&quot;1849&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1881&quot; data-start=&quot;1849&quot;&gt;stride가 너무 크거나(Large Stride)&lt;/li&gt;
&lt;li data-end=&quot;1937&quot; data-start=&quot;1882&quot;&gt;접근 주소가 불규칙하게 튀면(Random)&lt;br /&gt;&amp;rarr; 프리패처가 포기하거나 정확도가 떨어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2027&quot; data-start=&quot;1939&quot; data-ke-size=&quot;size16&quot;&gt;이 지점이 CPU가 좋아하는 데이터 배치의 현실적인 기준입니다.&lt;br /&gt;&lt;b&gt;연속 배열 + 규칙적 루프&lt;/b&gt;는 프리패처, 캐시, SIMD까지 한 번에 정렬됩니다.&lt;/p&gt;
&lt;hr data-end=&quot;2032&quot; data-start=&quot;2029&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2095&quot; data-start=&quot;2034&quot; data-ke-size=&quot;size26&quot;&gt;5) 구조체 설계의 정석: 무조건 alignas가 아니라 데이터 구겨넣기(Packing)가 먼저다&lt;/h2&gt;
&lt;p data-end=&quot;2173&quot; data-start=&quot;2096&quot; data-ke-size=&quot;size16&quot;&gt;정렬(Alignment)은 분명 도움이 됩니다. 특히 캐시 라인을 걸치지 않게 만들거나, 멀티스레드에서 라인 공유를 피하는 데도 쓰입니다. 하지만 무작정 alignas(64)부터 박으면 이런 문제가 생깁니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2317&quot; data-start=&quot;2217&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2271&quot; data-start=&quot;2217&quot;&gt;구조체가 작아도 &lt;b&gt;64B 패딩&lt;/b&gt;이 붙어 캐시 오염(cache pollution)이 생김&lt;/li&gt;
&lt;li data-end=&quot;2317&quot; data-start=&quot;2272&quot;&gt;결과적으로 실제 유효 데이터 대비 로드량이 늘어서 히트율이 떨어질 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2343&quot; data-start=&quot;2319&quot; data-ke-size=&quot;size16&quot;&gt;그래서 우선순위는 보통 이 순서가 맞습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2463&quot; data-start=&quot;2345&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;2377&quot; data-start=&quot;2345&quot;&gt;&lt;b&gt;필드 재배치 / 타입 정리&lt;/b&gt;로 패딩을 줄인다.&lt;/li&gt;
&lt;li data-end=&quot;2422&quot; data-start=&quot;2378&quot;&gt;남는 공간은 자주 쓰는 필드로 &lt;b&gt;메꿔서 64B를 꽉 채운다. (패킹)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2463&quot; data-start=&quot;2423&quot;&gt;그래도 필요할 때만 alignas(64) 같은 강제 정렬을 쓴다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;2494&quot; data-start=&quot;2465&quot; data-ke-size=&quot;size16&quot;&gt;그리고 여기서 다음 글 떡밥이 자연스럽게 이어집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2634&quot; data-start=&quot;2496&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2634&quot; data-start=&quot;2496&quot;&gt;구조체를 64B 정렬하는 이유는 속도만이 아니라&lt;br /&gt;멀티코어에서 &lt;b&gt;False Sharing(거짓 공유)&lt;/b&gt;를 피하기 위한 목적도 큽니다.&lt;br /&gt;(서로 다른 스레드가 같은 캐시 라인을 건드리면 Coherency Miss가 폭발합니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2639&quot; data-start=&quot;2636&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;AoS_vs_SoA.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oCwGZ/dJMcadARSK7/b7mnOFRGw7yNnVxnnbI0H0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oCwGZ/dJMcadARSK7/b7mnOFRGw7yNnVxnnbI0H0/img.png&quot; data-alt=&quot;AoS vs SoA&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oCwGZ/dJMcadARSK7/b7mnOFRGw7yNnVxnnbI0H0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoCwGZ%2FdJMcadARSK7%2Fb7mnOFRGw7yNnVxnnbI0H0%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;480&quot; height=&quot;480&quot; data-filename=&quot;AoS_vs_SoA.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AoS vs SoA&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-end=&quot;2695&quot; data-start=&quot;2641&quot; data-ke-size=&quot;size26&quot;&gt;6) AoS vs SoA: 데이터의 본질이 아닌 접근 패턴으로 결정한다&lt;/h2&gt;
&lt;p data-end=&quot;2730&quot; data-start=&quot;2696&quot; data-ke-size=&quot;size16&quot;&gt;여기서 정답을 단정하면 항상 사고가 납니다. 결론은 하나입니다.&lt;/p&gt;
&lt;blockquote data-end=&quot;2730&quot; data-start=&quot;2696&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; AoS/SoA는 취향이 아니라,&lt;br /&gt;루프의 형태로 결정한다. &lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 data-end=&quot;2800&quot; data-start=&quot;2771&quot; data-ke-size=&quot;size23&quot;&gt;AoS (Array of Structures)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2876&quot; data-start=&quot;2801&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2835&quot; data-start=&quot;2801&quot;&gt;개체 하나를 잡고 여러 필드를 같이 만지는 패턴에 유리&lt;/li&gt;
&lt;li data-end=&quot;2876&quot; data-start=&quot;2836&quot;&gt;단점: 특정 필드만 훑을 때 불필요한 데이터까지 같이 로드될 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1770780790174&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Agent { float pos, vel, health; };
Agent agents[100];&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;2907&quot; data-start=&quot;2878&quot; data-ke-size=&quot;size23&quot;&gt;SoA (Structure of Arrays)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3035&quot; data-start=&quot;2908&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2953&quot; data-start=&quot;2908&quot;&gt;같은 필드를 대량으로 훑는 패턴(예: pos만 10만 개 업데이트)에 유리&lt;/li&gt;
&lt;li data-end=&quot;2989&quot; data-start=&quot;2954&quot;&gt;장점: 캐시/프리패처/SIMD와 궁합이 좋은 경우가 많음&lt;/li&gt;
&lt;li data-end=&quot;3035&quot; data-start=&quot;2990&quot;&gt;단점: 개체 단위로 여러 필드를 동시에 만지면 오히려 산개 접근이 될 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1770780801204&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct AgentGroup { float pos[100], vel[100], health[100]; };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;3229&quot; data-start=&quot;3037&quot; data-ke-size=&quot;size16&quot;&gt;※ 참고로 &lt;span&gt;&lt;span&gt;Epic Games&lt;/span&gt;&lt;/span&gt;의 &lt;b&gt;&lt;span&gt;&lt;span&gt;Unreal Engine&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; 쪽에서 ECS 계열(예: Mass 같은 접근)을 떠올릴 수 있는데, 엔진 기능 자체보다 중요한 건 &amp;ldquo;내 루프가 무엇을 연속으로 훑는가&amp;rdquo;입니다. 기능 이름보다 &lt;b&gt;접근 패턴&lt;/b&gt;이 먼저입니다.&lt;/p&gt;
&lt;hr data-end=&quot;3234&quot; data-start=&quot;3231&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3279&quot; data-start=&quot;3236&quot; data-ke-size=&quot;size26&quot;&gt;7) 현대 하드웨어의 복잡성: L3 포함 정책은 유연해지는 추세&lt;/h2&gt;
&lt;p data-end=&quot;3318&quot; data-start=&quot;3280&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로, 멀티코어 시대에 L3 정책 이야기를 안 하면 반쪽입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3375&quot; data-start=&quot;3320&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3344&quot; data-start=&quot;3320&quot;&gt;L1/L2: 코어 전용, 빠르고 작음&lt;/li&gt;
&lt;li data-end=&quot;3375&quot; data-start=&quot;3345&quot;&gt;L3: 여러 코어가 공유, 상대적으로 크고 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3436&quot; data-start=&quot;3377&quot; data-ke-size=&quot;size16&quot;&gt;여기서 Inclusive / Non-Inclusive 얘기가 나오는데, 포스팅에서 중요한 태도는 이겁니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3550&quot; data-start=&quot;3438&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3462&quot; data-start=&quot;3438&quot;&gt;제조사별 경향성은 참고 가치가 있지만&lt;/li&gt;
&lt;li data-end=&quot;3550&quot; data-start=&quot;3463&quot;&gt;최근에는 코어 수 증가와 L3 효율 문제 때문에&lt;br /&gt;&lt;b&gt;두 진영 모두 정책을 더 유연하게 가져가는 추세&lt;/b&gt;라는 점을 같이 적는 게 신뢰도가 높습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3648&quot; data-start=&quot;3552&quot; data-ke-size=&quot;size16&quot;&gt;즉, 브랜드로 단정하기보단 &lt;b&gt;마이크로아키텍처/제품군 기준으로 확인&lt;/b&gt;하는 게 맞습니다.&lt;br /&gt;(특히 서버/워크스테이션 라인업은 정책이 다르게 나타나는 경우가 많습니다.)&lt;/p&gt;
&lt;p data-end=&quot;3763&quot; data-start=&quot;3650&quot; data-ke-size=&quot;size16&quot;&gt;여기서 &lt;span&gt;&lt;span&gt;Intel&lt;/span&gt;&lt;/span&gt; / &lt;span&gt;&lt;span&gt;AMD&lt;/span&gt;&lt;/span&gt; 비교를 할 때도 단정이 아니라 확인이 핵심입니다.&lt;/p&gt;
&lt;hr data-end=&quot;3768&quot; data-start=&quot;3765&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;3800&quot; data-start=&quot;3770&quot; data-ke-size=&quot;size26&quot;&gt;이 글의 결론, &amp;ldquo;캐시를 설계하라&amp;rdquo;&lt;/h2&gt;
&lt;p data-end=&quot;3828&quot; data-start=&quot;3801&quot; data-ke-size=&quot;size16&quot;&gt;CPU 최적화는 결국 이 두 문장으로 요약됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;3897&quot; data-start=&quot;3830&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;3856&quot; data-start=&quot;3830&quot;&gt;&lt;b&gt;연산보다 로드가 먼저 병목이다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;3897&quot; data-start=&quot;3857&quot;&gt;&lt;b&gt;캐시는 라인 단위로 움직이고, 미스는 4C로 구분해야 한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;3929&quot; data-start=&quot;3899&quot; data-ke-size=&quot;size16&quot;&gt;다음 글에서 이어설명할 주제는 아래와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;4047&quot; data-start=&quot;3931&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3968&quot; data-start=&quot;3931&quot;&gt;Coherency Miss와 &lt;b&gt;False Sharing&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;4014&quot; data-start=&quot;3969&quot;&gt;왜 alignas(64)가 속도가 아니라 멀티코어 안정성의 문제인지&lt;/li&gt;
&lt;li data-end=&quot;4047&quot; data-start=&quot;4015&quot;&gt;그리고 멀티스레드에서 캐시 라인을 어떻게 분리/배치할지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이전글&lt;/h2&gt;
&lt;figure id=&quot;og_1772667709013&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;당신의 멀티스레드가 느린 이유: False Sharing과 alignas(64)의 진실&quot; data-og-description=&quot;Coherency Miss(일관성 미스)로 보는캐시 라인 전쟁과 해결 전략,alignas(64)는 속도가 아니라멀티코어 안정성이다.싱글 스레드 최적화는 보통 캐시 히트율로 설명이 끝납니다.하지만 멀티스레드에 들&quot; data-og-host=&quot;chessire.tistory.com&quot; data-og-source-url=&quot;https://chessire.tistory.com/entry/multithreading-false-sharing-alignas64&quot; data-og-url=&quot;https://chessire.tistory.com/entry/multithreading-false-sharing-alignas64&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/inx2Y/dJMb88eYomP/SogSyqnhQ0kFI3vVuIqj5k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bbvKvf/dJMb87NT8NJ/dgfDuL59VK61A7kpabS1SK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dm9mmE/dJMb83kqFdH/VL4YJ5Y0kkk9aZasmbwGRK/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot;&gt;&lt;a href=&quot;https://chessire.tistory.com/entry/multithreading-false-sharing-alignas64&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chessire.tistory.com/entry/multithreading-false-sharing-alignas64&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/inx2Y/dJMb88eYomP/SogSyqnhQ0kFI3vVuIqj5k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bbvKvf/dJMb87NT8NJ/dgfDuL59VK61A7kpabS1SK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/dm9mmE/dJMb83kqFdH/VL4YJ5Y0kkk9aZasmbwGRK/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024');&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;당신의 멀티스레드가 느린 이유: False Sharing과 alignas(64)의 진실&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Coherency Miss(일관성 미스)로 보는캐시 라인 전쟁과 해결 전략,alignas(64)는 속도가 아니라멀티코어 안정성이다.싱글 스레드 최적화는 보통 캐시 히트율로 설명이 끝납니다.하지만 멀티스레드에 들&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chessire.tistory.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;</description>
      <category>Notes/Computer Science</category>
      <category>Alignment</category>
      <category>AOS</category>
      <category>cache</category>
      <category>CacheMiss</category>
      <category>CPU</category>
      <category>FalseSharing</category>
      <category>Locality</category>
      <category>Prefetch</category>
      <category>SOA</category>
      <category>stride</category>
      <author>체셔 Kim</author>
      <guid isPermaLink="true">https://chessire.tistory.com/106</guid>
      <comments>https://chessire.tistory.com/entry/cpu-cache-locality-alignment-soa-aos#entry106comment</comments>
      <pubDate>Thu, 12 Mar 2026 08:06:58 +0900</pubDate>
    </item>
  </channel>
</rss>