<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Sijun Yang</title>
      <link>https://sijun-yang.com/</link>
      <description>Sijun Yang의 블로그</description>
      <generator>Zola</generator>
      <language>ko</language>
      <atom:link href="https://sijun-yang.com/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Thu, 30 Apr 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>[월간 기록] 2026년 4월</title>
          <pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-2026-04/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-2026-04/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-2026-04/">&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;geu-oe-sujibhan-geul&quot;&gt;그 외 수집한 글&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;jungle-sw-ai-lab-hwaldong&quot;&gt;Jungle SW-AI Lab 활동&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;5juca&quot;&gt;5주차&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;6juca&quot;&gt;6주차&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;7juca&quot;&gt;7주차&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;8juca&quot;&gt;8주차&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jjalbeun-saenggag&quot;&gt;짧은 생각&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;근황과 요즘 하는 생각&lt;&#x2F;p&gt;</description>
      </item>
      <item>
          <title>Week 07: 탐험 준비</title>
          <pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week07/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week07/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week07/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-jagseong-yejeong&quot;&gt;목표 1. 작성 예정&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 작성 예정&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-2-jagseong-yejeong&quot;&gt;목표 2. 작성 예정&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 작성 예정&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-1&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-1&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h2 id=&quot;geu-oe-jageob&quot;&gt;그 외 작업&lt;&#x2F;h2&gt;
&lt;p&gt;핵심 목표나 관련있는 내용은 아닌데, 따로 했던 활동이나 소개하고 싶은 것들 정리&lt;&#x2F;p&gt;
&lt;p&gt;예: Jungle Bell 개발, Skill 만든거 공유, 오픈소스 기여 등 핵심 주제는 아닌데 공유하고 싶은것들 자유롭게&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;작성 예정&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;jagseong-yejeong&quot;&gt;작성 예정&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;작성 예정&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;suyokodinghoe-hugi&quot;&gt;수요코딩회 후기&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;jal-doen-jeom-yujihal-jeom&quot;&gt;잘 된 점 &#x2F; 유지할 점&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;작성 예정&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;aswiun-jeom-gaeseonhal-jeom&quot;&gt;아쉬운 점 &#x2F; 개선할 점&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;작성 예정&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;koeotaim-hyeobeob-hoego&quot;&gt;코어타임 &#x2F; 협업 회고&lt;&#x2F;h3&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h3 id=&quot;haegsim-yeogryang-mogpyo-hoego&quot;&gt;핵심 역량 목표 회고&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;jal-doen-jeom&quot;&gt;잘 된 점&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gomin&quot;&gt;고민&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daeum-jucae-sidohal-geos&quot;&gt;다음 주차에 시도할 것&lt;&#x2F;h4&gt;
&lt;p&gt;작성 예정&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Week 06: 탐험 준비</title>
          <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week06/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week06/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week06/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-jaryogujoreul-jigjeob-guhyeonhago-silje-raibeureoriyi-guhyeon-bangsiggwa-dongjag-weonrireul-bunseoghagi&quot;&gt;목표 1. 자료구조를 직접 구현하고, 실제 라이브러리의 구현 방식과 동작 원리를 분석하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 구현, 문제해결, 학습 민첩성&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;기본 자료구조를 직접 빠르게 구현해 본 뒤, GLib 같은 대표적인 C 자료구조 라이브러리를 사용하거나 내부 구현을 살펴볼 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;외부 사용을 전제로 메모리가 어떻게 관리되는지, 어떤 인터페이스를 제공하는지 등을 분석하면서 C와 자료구조에 대한 이해를 더 깊게 가져가고자 한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;과제를 보지 못한 상태에서 설정한 목표라서 자료구조를 구현하는 줄 알고 이러한 목표를 설정했는데, 실제로는 자료구조를 사용한 코딩 테스트 문제 풀이와 비슷해서 자료구조 구현은 하지 않았다.&lt;&#x2F;p&gt;
&lt;p&gt;알고리즘 문제는 금, 토, 일요일까지 해서 다 구현하고 AI 기반 피드백으로 자체 평가까지 완료했다.&lt;&#x2F;p&gt;
&lt;p&gt;이후 월, 화에 기존에 존재하는 라이브러리를 분석했다.&lt;&#x2F;p&gt;
&lt;p&gt;이전부터 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sijun-yang.com&#x2F;jungle&#x2F;clang-data_structure&#x2F;&quot;&gt;C에서 자료구조 사용법과 내부 메모리 관리가 궁금했던지라 찾아보고 가볍게 정리하여 글&lt;&#x2F;a&gt;을 썼다.&lt;&#x2F;p&gt;
&lt;p&gt;그리고 그 과정에서 찾아본 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sijun-yang.com&#x2F;jungle&#x2F;jungle-tsoding-1st&#x2F;&quot;&gt;Tsoding의 유튜브 내용에 대한 메모&lt;&#x2F;a&gt;도 남겨두었다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;목표했던 자료구조 직접 구현은 하지 못했고, 라이브러리 분석은 전부 완성하지 못했다.&lt;&#x2F;p&gt;
&lt;p&gt;하지만 자료구조 구현은 필요하긴 한데, 과제랑 연결되어서 설정한 면도 있어서 라이브러리 분석을 통해 자료구조의 메모리(더 크게 보면 C에서 메모리 관리에 대한 이해)를 익혔다는 점에서 의미가 있지 않나.&lt;&#x2F;p&gt;
&lt;p&gt;아직 완성하지 못한 자료구조 정리 글은 일요일의 자유 시간을 활용해서 완성할 계획임.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-2-hagseubhan-naeyonggwa-jaryoreul-time-gongyuhagi&quot;&gt;목표 2. 학습한 내용과 자료를 팀에 공유하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 협업, 태도&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-1&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;자료구조는 비교적 익숙한 분야라, 필요하면 개념을 설명하거나 관련 자료를 공유하는 식으로 좀 더 적극적으로 참여해 보려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 팀원 분위기를 보니 다 같이 개념을 그리며 익혀 가는 스타일은 아닌 것 같았고, 다들 기본 개념도 어느 정도는 잡혀 있는 상태로 보인다.&lt;&#x2F;p&gt;
&lt;p&gt;그래서 팀원들이 부담을 느끼지 않는 선에서 참고할 만한 자료나 내가 괜찮았던 시도, 경험을 가볍게 공유하고 도움이 필요할 때 같이 고민해 보는 식으로 협업할 계획을 세웠다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;CLion용 devcontainer 설정, AddressSanitizer와 Valgrind 같은 도구를 공유하였다. 또한 수요코딩회에서 참고하기 좋은 간단한 참고 자료들도 공유하였다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-1&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;과제가 새로운 개념이나 익혀야 할 지식이 나오지 않고, 알고리즘적인 부분이 많아서 생각보다 많이 공유하지 못했다.&lt;&#x2F;p&gt;
&lt;p&gt;부분적으로 달성했지만, 팀원들에게 긍정적인 피드백을 받았으므로 강요하지 않도록 주의하면서 계속 진행하면 좋을 듯하다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-3-aireul-hwalyonghae-jungle-belle-singyu-gineungeul-cugahago-beojeon-0-3-0eul-baepohagi&quot;&gt;목표 3. AI를 활용해 Jungle Bell에 신규 기능을 추가하고 버전 0.3.0을 배포하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: AI 활용, 품질, 유지보수&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;메인 커리큘럼과 직접 연결되는 목표는 아니지만, AI를 활용한 유지보수와 제품 개선 경험을 쌓는다는 점에서 별도 목표로 두었다. 대신 우선순위는 앞선 두 목표보다 낮게 유지하려 했다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-2&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-bell&#x2F;issues&quot;&gt;GitHub 이슈&lt;&#x2F;a&gt;를 기준으로 필요한 기능을 하나씩 추가하고, 작은 단위로 버전 업데이트를 할 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;목표는 급식 알림 기능과 여러 편의성 패치를 포함한 &lt;code&gt;v0.3.0&lt;&#x2F;code&gt;까지 배포하는 것이다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-2&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;실제로는 신규 기능보다 UI 수정, 내부 코드 리팩터링, 자잘한 편의성 개선 위주로 진행했고, 그 결과 &lt;code&gt;v0.2.2&lt;&#x2F;code&gt;까지 정리했다.&lt;&#x2F;p&gt;
&lt;p&gt;주차가 진행될수록 메인 커리큘럼과 수요코딩회 회고에 더 많은 시간을 쓰게 되어, 계획에서 생각했던 메뉴 알리미 기능까지는 진행하지 못했다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-2&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;결론적으로 목표인 &lt;code&gt;v0.3.0&lt;&#x2F;code&gt; 출시는 달성하지 못했다.&lt;&#x2F;p&gt;
&lt;p&gt;급식 알림 기능을 추가하는 건 투자 대비 리턴이 크지 않다고 판단했다. (특히 데스크톱 앱에선)&lt;&#x2F;p&gt;
&lt;p&gt;그래서 현재는 메뉴 알리미를 크게 확장하기보다는, 정글 오픈 채팅 바로가기 링크를 추가하는 정도의 작은 개선만 기획하고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;애초에 Jungle Bell을 개발한 이유는, 오픈 소스에 본격적으로 기여하기 전에 AI를 활용한 유지 보수와 제품 개선 경험을 가볍게 익혀 보려는 데 있었다.
그런데 유지 보수와 추가 기능까지 계속 신경 쓰다 보니, 이대로라면 끝날 때까지 이 서비스를 계속 붙잡고 있게 될 것 같아 범위를 줄이려는 것도 있다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;04-09-gimhyeonsu-kocinim-keopicaes&quot;&gt;04&#x2F;09 김현수 코치님 커피챗&lt;&#x2F;h3&gt;
&lt;p&gt;회고가 끝난 뒤 1층 라운지에서 약 1시간 20분 정도 이야기를 나눴다. 자세한 내용은 개인적으로 정리했지만, 공유하고자 하는 내용만 작성해 보았다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;질문: 발표에서는 무엇을 공유하는 게 좋은가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;발표는 같아도 되고 달라도 되지만, 중요한 것은 듣는 사람에게 본질적으로 도움이 되는 내용이냐는 점이다.&lt;&#x2F;li&gt;
&lt;li&gt;특히 실패했던 지점, 왜 막혔는지, 어떻게 극복하려 했는지, 다음에는 어떤 전략을 시도할지 같은 내용은 실제로 해 본 사람만 말할 수 있어서 더 가치가 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;핵심: AI를 많이 써 봐야 비판적으로 볼 수 있다&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;AI 결과를 맹목적으로 받아들이지 않고, 왜 이런 결과가 나왔는지, 다른 선택지는 없는지, 지금 상황에 맞는 선택인지 따져보는 태도가 중요하다.&lt;&#x2F;li&gt;
&lt;li&gt;이런 비판적 사고는 AI에게만 적용되는 것이 아니라, 원래 사람의 코드나 설명을 볼 때도 필요한 태도이다.&lt;&#x2F;li&gt;
&lt;li&gt;하나의 정답만 붙드는 것이 아니라, 상황에 따라 다른 선택이 가능하다는 시각을 가져야 한다. (비용과 서버 안전성의 트레이드오프를 예시로 들었음.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;질문: 어려운 과제는 어떤 식으로 접근하면 좋은가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;본인이 수요코딩회에서 톱다운으로 접근하는 방법을 소개했다.
&lt;ul&gt;
&lt;li&gt;본인도 수요코딩회 과제를 해 보는데, 2시간 정도 하면 결과물이 나온다. 본인이 아무 핵심도 모른다고 생각하고 접근한다.&lt;&#x2F;li&gt;
&lt;li&gt;처음부터 구현으로 들어가기보다, AI를 활용하면서 먼저 과제가 최소한 무엇을 해야 하는지 3가지로 짧게 정의해 달라고 하고, 그 정의를 다시 3가지 핵심으로 나누는 식으로 재귀적으로 들어간다.&lt;&#x2F;li&gt;
&lt;li&gt;충분히 전체 구조가 구체적으로 잡히면 의사 코드나 더미 코드 수준으로 맞춘다. 그럼 구현에 들어가기 전에도 전체 구조를 이해할 수 있다.&lt;&#x2F;li&gt;
&lt;li&gt;이러면 구현에 들어가기 전에도 전체 구조를 이해할 수 있고 협업할 때도 합의 지점이 생긴다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;하지만 이게 유일한 방법은 아니며, 본인에게 잘 맞는 방법일 뿐임. 본인이 본 사람들 중에는 코드를 따라 치면서 전체 구조를 이해하는 사람도 있었다.&lt;&#x2F;li&gt;
&lt;li&gt;(내 생각: 이런 톱다운 접근은 구현이나 과제뿐만 아니라 학습 등 범용적으로 톱다운으로 접근할 때 써 볼 수 있을 것 같아 여러 부분에 적용해 볼 예정.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;핵심: 수요코딩회에서는 의심하고 다음 시도를 만드는 경험 자체가 중요하다&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;이번 방식이 완벽했는지보다, 이번에는 잘 안 됐으니 다음에는 다르게 해 봐야겠다는 고민이 실제로 나오고 있다는 점 자체가 의미 있다.&lt;&#x2F;li&gt;
&lt;li&gt;어떤 방법이 맞는지 스스로 의심하고 다른 시도를 해 보려는 흐름이 생기고 있다면, 기대했던 모습과 정확히 같지 않더라도 좋은 과정이라고 생각한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;질문: AI를 써도 직접 코딩하며 익히는 과정이 왜 필요한가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;톱다운 접근이나 AI 활용이 도움이 될 수는 있지만, 그것이 직접 부딪히며 익히는 경험 자체를 대체하지는 못한다.&lt;&#x2F;li&gt;
&lt;li&gt;특히 익숙하지 않은 단계에서는 직접 코드를 읽고 쓰면서 익숙해지는 시간이 필요하다.&lt;&#x2F;li&gt;
&lt;li&gt;생성된 코드를 오래 읽는 것과 실제로 코드를 써 본 경험은 다르며, 코드를 제대로 읽으려면 결국 직접 코딩해 본 경험이 있어야 한다.&lt;&#x2F;li&gt;
&lt;li&gt;단순히 결과를 내는 수준을 넘어서 구조와 맥락까지 이해하고 싶다면, 직접 부딪히는 과정이 필요하다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;질문: AI를 도구로 본다면, sanitizer나 Valgrind 같은 도구를 사용하는 건 어떤가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;조금 조심스럽지만 시대에 맞는 도구는 쓰는 게 맞고, 예전의 불편한 방식만 고집하는 것을 강요할 필요는 없지 않나 싶다.&lt;&#x2F;li&gt;
&lt;li&gt;중요한 것은 도구를 쓰지 말아야 한다는 게 아니라, 도구를 딸깍 수준으로만 소비하지 않고 스스로 고민하면서 쓰는 상태에 도달하는 것이다.&lt;&#x2F;li&gt;
&lt;li&gt;도구의 도움을 받더라도 그 결과를 해석하고, 다른 도구가 있더라도 무작정 의존하지 않으면서 문제를 이해하려는 태도가 있으면 그것도 충분히 의미가 있다.&lt;&#x2F;li&gt;
&lt;li&gt;결국 AI나 도구가 없는 시대를 상정하기보다, 지금 시대의 도구를 쓰면서도 다른 사람보다 한 단계 더 고민하는 사람이 되는 쪽이 더 현실적인 방향이다.&lt;&#x2F;li&gt;
&lt;li&gt;(내 생각: 그렇게 따지면 IDE나 구글링도 쓰지 않던 시대가 있는데, 굳이 그럴 필요가 있나. 다만 예전의 도구나 도구가 없던 시절의 방식을 알면, 선택 가능한 방법 중 하나로 유용하게 쓸 수는 있겠다.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;핵심: WIL과 블로그 기록은 나중에 강한 증거가 될 수 있다&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;매일의 시도, 실패, 성장 과정을 꾸준히 남긴 기록은 나중에 다른 사람이 보았을 때도 이 사람이 실제로 어떤 태도로 시간을 보냈는지 보여주는 증거가 될 수 있다.&lt;&#x2F;li&gt;
&lt;li&gt;모든 글을 다 읽지는 않더라도, 일정 기간 동안 꾸준히 남아 있는 기록과 그 안의 밀도만으로도 좋은 인상을 줄 수 있는 경우가 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;suyokodinghoe-hugi&quot;&gt;수요코딩회 후기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-week6&quot;&gt;Week 6 수요코딩회 저장소&lt;&#x2F;a&gt;
와 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-week6&#x2F;blob&#x2F;main&#x2F;README_%EC%88%98%EC%9A%94%EC%BD%94%EB%94%A9%ED%9A%8C_%EC%9A%B4%EC%98%81%EC%95%88_%EB%B0%B0%EA%B2%BD%EC%A0%95%EB%A6%AC.md&quot;&gt;운영안 배경 정리&lt;&#x2F;a&gt;
에 이번 시도의 배경을 정리해 두었다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jal-doen-jeom-yujihal-jeom&quot;&gt;잘 된 점 &#x2F; 유지할 점&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;문제의식을 가지고 시도&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;이번에는 기존의 널리 쓰이는 방식인 AI에 의존하는 문제를 해결하기 위해 새로운 시도를 했다.&lt;&#x2F;li&gt;
&lt;li&gt;시행착오는 있었지만 이런 방향성 자체는 여전히 맞다고 생각한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;AI 프롬프트 남겨서 회고 가능한 구조 만들기&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;각 팀원의 AI 사용 흐름과 그 결과를 프롬프트와 코드로 묶어서 평가할 수 있게 되었다.&lt;&#x2F;li&gt;
&lt;li&gt;해건님의 아이디어에서 시작해서, 구체화는 팀이 함께 진행했다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;이 분석을 통해서 프롬프트를 쓸 때, 필요한 정보만 주는 것이 더 중요하다는 것을 알 수 있었다.
&lt;ul&gt;
&lt;li&gt;우리는 프로젝트를 여러 단위로 쪼개서 개발을 했는데, 이때 전체 단위에 대한 컨텍스트를 준 팀원의 결과물은 불필요한 부분까지 구현한 반면, 개발하려는 단위만 제공한 경우에는 필요한 부분만 구현했다는 것을 실제 비교를 통해 알 수 있었다.&lt;&#x2F;li&gt;
&lt;li&gt;이론적으로는 알고 있었지만, 이렇게 실제 경험과 비교하며 더 잘 알게 된 것 같다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;aswiun-jeom-gaeseonhal-jeom&quot;&gt;아쉬운 점 &#x2F; 개선할 점&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;한 번에 너무 많은 시도&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;GitHub 도구 사용법, 코드 리뷰, 로그 분석, 발표 개선, 구현 실험까지 새로운 시도가 많았다.&lt;&#x2F;li&gt;
&lt;li&gt;그러다 보니 과제에 대한 이해도나 수행도 측면에서는 오히려 기존보다 부족했던 것 같다.&lt;&#x2F;li&gt;
&lt;li&gt;시행착오 시간을 고려해서 목표를 낮추고, 목표를 조금 낮추더라도 작은 시도라도 완료하는 게 중요할 것 같다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;인지 부하를 줄이자&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;팀원의 코드를 빠르게 리뷰하면서 동시에 구현 방향까지 함께 맞추려 했고, 시간에 쫓겨 후반부에는 날림으로 끝났다.&lt;&#x2F;li&gt;
&lt;li&gt;페어 프로그래밍을 해서 코드 리뷰 양을 줄이거나, 의사 코드를 다 같이 짜고 각자 개발하는 등 인지 부하를 줄이는 방법이 필요하다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프롬프트 로그 자체로는 의미가 없다 &amp;amp; 도구의 부족함&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;프롬프트 로그와 커밋 내역 기반으로 피드백을 받은 건 좋았지만, 과정이 많이 자동화되어 있다 보니, 사용자의 행동이나 시행착오가 없이 결론만 받아서 잘 이해하고 오래 남는 느낌은 아니었다.&lt;&#x2F;li&gt;
&lt;li&gt;더 적절한 &lt;code&gt;수행&#x2F;피드백&lt;&#x2F;code&gt; 루프를 만들어야 하고, 지금으로선 큰 의미가 없는 것 같다.&lt;&#x2F;li&gt;
&lt;li&gt;그리고 로그 수집 도구로서 Hooks나 Prompt History도 괜찮긴 한데, 더 다양한 정보와 편의성이 좋은 도구를 찾아봐야 할 것 같다.&lt;&#x2F;li&gt;
&lt;li&gt;여러 주차를 반복하면서 꾸준히 개선해 봐야 할 것 같다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;koeotaim-hyeobeob-hoego&quot;&gt;코어타임 &#x2F; 협업 회고&lt;&#x2F;h3&gt;
&lt;p&gt;공식적인 코어타임은 없었지만, 우리끼리 짧게라도 진행 상황을 공유하는 시간을 만들었다.&lt;&#x2F;p&gt;
&lt;p&gt;이 시간에는 CLion용 devcontainer 설정, AddressSanitizer나 Valgrind 같은 도구처럼 바로 써먹을 수 있는 정보나 과제에서 실수하기 좋은 부분(구현과 무관한 과제 자체에서 잘못된 부분)을 주고받았다.
30분 이내로 끝낼 수 있어 부담 없이 할 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;코어타임은 다음 주에도 도입하고 싶다. 강제하지 않으면 이런 식으로 현황과 정보를 공유하는 게 생각보다 잘 이루어지지 않을 것 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;haegsim-yeogryang-mogpyo-hoego&quot;&gt;핵심 역량 목표 회고&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;jal-doen-jeom&quot;&gt;잘 된 점&lt;&#x2F;h4&gt;
&lt;p&gt;하나라도 완벽하게 해낸 목표가 없었지만, 앞으로의 방향을 좀 더 명확하게 잡을 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;특히 김현수 코치님과의 커피챗을 통해서 수요코딩회 운영 방식과 AI 활용 방식에 대해 어느 정도 확신이 생기게 되었는데, 의도하진 않았지만 아주 큰 의미가 있었다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gomin-1-haegsim-yeogryang-mogpyoe-saideu-peurojegteureul-eodiggaji-pohamhal-geosinga&quot;&gt;고민 1: 핵심 역량 목표에 사이드 프로젝트를 어디까지 포함할 것인가?&lt;&#x2F;h4&gt;
&lt;p&gt;Jungle Bell처럼 의미 있는 활동이더라도, 메인 커리큘럼과 직접 연결되지 않으면 결국 우선순위에서 밀리게 된다. 개인적인 목표가 핵심 목표에 적절하진 않다고 느꼈다. 다음에는 별도 템플릿으로 관리하거나,
제외하는 게 나을 듯하다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gomin-2-sigan-gwanriwa-sumyeon-sigan-hwagbohagi&quot;&gt;고민 2: 시간 관리와 수면 시간 확보하기&lt;&#x2F;h4&gt;
&lt;p&gt;이번 주에는 늦게 들어간 날이 여러 번 있었고, 결국 이번 주차의 평균 수면 시간(일요일 제외)이 거의 5시간 수준으로 줄어들었다.
이 글을 쓰는 목요일 시점에는 커피를 마셔도 졸릴 정도로 피곤해서 상태가 좋지 않다고 느꼈다. 그리고 말하는 거나 이해하는 것에 있어서 평소보다 잘 되지 않고, 인지 능력 저하가 체감되었음.&lt;&#x2F;p&gt;
&lt;p&gt;여러 원인이 있겠지만, 과제가 어렵다기보다는 사람들과 이야기가 재미있어서 늦게 가거나(&lt;del&gt;오전 12시가 넘어가면 노가리 까는 게 3배는 재밌어지는 것 같다&lt;&#x2F;del&gt;),
보상 심리 때문에 30분씩은 폰을 보고 잔다거나 하는 필수적이지 않은 활동은 조절할 필요가 있을 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;하지만 멘탈 유지에는 이런 활동이 필요하다고 생각하기 때문에, 시간을 낮으로 옮기거나 제한 시간을 정하는 등의 최소한의 시간 관리는 해야 할 것 같다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daeum-jucae-sidohal-geos&quot;&gt;다음 주차에 시도할 것&lt;&#x2F;h4&gt;
&lt;p&gt;평균 최소 수면 시간 7시간을 확보하도록 시간 관리에 신경을 쓸 예정이다.&lt;&#x2F;p&gt;
&lt;p&gt;핵심 계획을 과제를 모르는 상태에서 세우니 잘 지켜지지 않는 것 같았다. 다음 주부터는 초반 이해를 어느 정도 잡은 뒤, 늦어도 금요일 저녁까지 학습 목표를 정할 생각이다.&lt;&#x2F;p&gt;
&lt;p&gt;공부나 수요코딩회에서 김현수 코치님과 커피챗을 통해서 알게 된 것처럼 &lt;code&gt;3가지 핵심 질문으로 이해하며 재귀적으로 TOP-Down 접근&lt;&#x2F;code&gt;하는 방식이 좋아 보여 적용해 볼 계획이다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>C에서의 자료구조 라이브러리 구현 알아보기</title>
          <pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/clang-data-structure/</link>
          <guid>https://sijun-yang.com/jungle/clang-data-structure/</guid>
          <description xml:base="https://sijun-yang.com/jungle/clang-data-structure/">&lt;p&gt;항상 궁금했던 게, C에서는 data structures(자료구조들)를 메모리에서 어떻게 관리하는지임.&lt;&#x2F;p&gt;
&lt;p&gt;크게 2가지인데, element(원소)의 관리와 data structure 자체의 관리임.&lt;&#x2F;p&gt;
&lt;p&gt;암튼 그걸 위해서 C의 참고용으로 쓸 만한 자료구조 라이브러리들을 찾아봤는데, 일단은 이것들로 찾아볼 듯? (+ 그리고 이해를 돕기 위한 Rust와의 비교)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gnome&#x2F;glib&quot;&gt;glib&lt;&#x2F;a&gt; - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gtk.org&#x2F;glib&#x2F;data-structures.html&quot;&gt;docs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fragglet&#x2F;c-algorithms&quot;&gt;c-algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;srdja&#x2F;Collections-C&quot;&gt;Collections-C&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;elementwa-data-structureyi-memori-gwanri&quot;&gt;element와 data structure의 메모리 관리&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;elementyi-memori-gwanri&quot;&gt;element의 메모리 관리&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;munje&quot;&gt;문제&lt;&#x2F;h4&gt;
&lt;p&gt;Rust와 비교하면 이해하기 좋을 거 같은데, Rust의 소유권을 대충이나마 알고 나서 C의 메모리 관리를 어떤 식으로 하는 게 (일반적으로) 좋은지 좀 더 이해하게 되긴 했는데&lt;&#x2F;p&gt;
&lt;p&gt;그래도 여전히 이해가 안 되는 게 있다면, element의 관리임. Rust야 소유권이 넘어가지만, C는 언어 차원에서 소유권 개념이 없으니 호출자와 data structure 자체 중 누가 관리하는지 정해야 하는데, 이게 어떻게 되는 건지?&lt;&#x2F;p&gt;
&lt;p&gt;예로 들어 특정 함수 내부에서 배열을 받아서 특정 인덱스의 element를 Rust처럼 “빌린다&#x2F;넘긴다”로 구분해서 처리하는 게 아니라, C에서는 그냥 값이나 포인터를 다루는 것뿐이라 그 포인터가 가리키는 대상의 수명과 해제 책임이 코드만 보고는 바로 드러나지 않는다. 그래서 이게 빌리는 건지, 넘기는 건지, 지우는 건지도 명시가 없으면 되게 애매해지는 거 같음.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;josa&quot;&gt;조사&lt;&#x2F;h4&gt;
&lt;p&gt;AI와 실제 공식문서, 코드 약간 참고(전부는 아님)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;C 범용 자료구조 라이브러리의 container 특징&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;pointer container(포인터 저장형 컨테이너), 기본 non-owning&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;포인터만 저장&lt;&#x2F;li&gt;
&lt;li&gt;pointee(포인터가 가리키는 대상) 자체의 해제는 보통 호출자가 직접 관리&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;pointer container + destroy callback&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;여전히 Rust처럼 언어 차원의 ownership은 아님&lt;&#x2F;li&gt;
&lt;li&gt;일부 라이브러리&#x2F;data structure는 element 제거 또는 data structure 파괴 시 호출할 &lt;strong&gt;destroy callback&lt;&#x2F;strong&gt;을 지원&lt;&#x2F;li&gt;
&lt;li&gt;개별 element에 연결된 정리 동작을 data structure 동작에 연결하는 방식&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;pointer container + free-all 계열 API&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;일부 라이브러리&#x2F;data structure는 callback 대신&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;destroy_free&lt;&#x2F;code&gt;, &lt;code&gt;remove_all_free&lt;&#x2F;code&gt; 같은 식으로 &lt;strong&gt;전체 정리 시 포인터가 가리키는 대상까지 한꺼번에 free하는 API&lt;&#x2F;strong&gt;를 제공&lt;&#x2F;li&gt;
&lt;li&gt;보통 개별 element 제거 시마다 자동으로 동작하는 방식과는 구분됨 (callback과 free-all 둘 다 제공할 수도 있음)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;value-copy container(값 복사 저장형 컨테이너)&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;값을 복사해서 저장&lt;&#x2F;li&gt;
&lt;li&gt;이 경우 container는 “복사해 둔 value(값)”의 storage(저장소)는 관리하지만, 그 값 안에 포인터가 있으면 그 내부까지 자동으로 관리하는 건 아님&lt;&#x2F;li&gt;
&lt;li&gt;따라서 포인터 대상의 수명까지 포함한 deep copy&#x2F;deep free 여부를 별도로 봐야 함&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;실제 라이브러리 기준으로&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GLib&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GArray&lt;&#x2F;code&gt;: 값 저장형&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;GPtrArray&lt;&#x2F;code&gt;: 포인터 저장형, destroy callback을 붙여서 element 제거&#x2F;파괴 시 정리 동작을 연결 가능&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;GList&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;GQueue&lt;&#x2F;code&gt;: 기본적으로 data 포인터 저장형&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;GHashTable&lt;&#x2F;code&gt;: 기본 삽입은 복사 아님, 수명 관리를 사용자가 의식해야 함. 대신 key&#x2F;value destroy function을 지정할 수 있음&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;c-algorithms&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fragglet.github.io&#x2F;c-algorithms&#x2F;doc&#x2F;&quot;&gt;공식문서&lt;&#x2F;a&gt;에서 모두 &lt;code&gt;void *&lt;&#x2F;code&gt; 기반 포인터 저장형 container이라고 말함.&lt;&#x2F;li&gt;
&lt;li&gt;일부 data structure는 free callback 등록으로 정리 동작을 연결 가능&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Collections-C&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;pointer container와 value-copy 성격의 sized container가 분리&lt;&#x2F;li&gt;
&lt;li&gt;pointer container 쪽은 &lt;code&gt;destroy_free&lt;&#x2F;code&gt;, &lt;code&gt;remove_all_free&lt;&#x2F;code&gt; 같은 free-all 계열 API 제공&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;jeongri&quot;&gt;정리&lt;&#x2F;h4&gt;
&lt;p&gt;정리해보자면 value-copy container의 경우 container가 자기 내부에 복사해 둔 value의 storage를 관리한다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 이걸 Rust 식으로 “소유권이 container에게 있다”라고 그대로 말하면 약간 오해의 소지가 있는데, C에는 그런 언어 차원의 개념이 없고, 그냥 container가 복사본을 보관하고 그 복사본의 수명을 관리한다고 보는 편이 더 정확함.&lt;br &#x2F;&gt;
그래서 이런 container는 포인터가 아닌 값 자체를 저장할 때 쓰는 경우가 자연스럽다.&lt;br &#x2F;&gt;
따라서 container에서 element를 제거할 때는 그 복사되어 저장된 value가 들어 있던 slot(슬롯)이 자연스럽게 정리된다.&lt;&#x2F;p&gt;
&lt;p&gt;C에서 stored value가 pointer인 경우, 처리가 더 까다로운데,
Rust와 다르게 함수&#x2F;타입 시스템 차원에서 ownership에 따라 다르게 처리해주지 않으므로, 필요에 따라 직접 free를 호출해야 함.
그렇지 않으면 메모리 누수가 발생할 수 있음.&lt;&#x2F;p&gt;
&lt;p&gt;Rust와 달리 ownership 개념이 없으므로, element를 가져와 data structure에선 삭제하고 free하지 않고 남기는 경우도 있을 거라서 그럼.&lt;br &#x2F;&gt;
따라서 이걸 포인터가 가리키는 대상의 메모리까지 해제하는 건지 아니면 그냥 빼오기만 하는 건지는 API 문서나 함수 의미로 직접 정해져 있어야 하고, 사용자가 그걸 의식하고 써야 함.&lt;&#x2F;p&gt;
&lt;p&gt;대신 remove나 replace가 많이 발생하는 data structure의 경우 (정확히는 data structure 조작이 일어날 때, 그 element가 가리키는 대상의 메모리도 같이 정리되어야 하는 상황)에서,
사용자의 실수 방지나 편의성 처리를 위해 destroy callback을 지원한다.
대표적으로 GLib의 &lt;code&gt;GPtrArray&lt;&#x2F;code&gt;와 &lt;code&gt;GHashTable&lt;&#x2F;code&gt;이 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;data-structureyi-memori-gwanri&quot;&gt;data structure의 메모리 관리&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;munje-1&quot;&gt;문제&lt;&#x2F;h4&gt;
&lt;p&gt;이제 element의 메모리 관리는 대충 이해했는데, data structure의 메모리 관리는 여전히 잘 모르겠음.&lt;&#x2F;p&gt;
&lt;p&gt;contiguous memory(연속 메모리)를 사용하는 배열 기반 data structure는 비교적 이해하기 쉽다.&lt;br &#x2F;&gt;
보통 &lt;code&gt;size&lt;&#x2F;code&gt;와 &lt;code&gt;capacity&lt;&#x2F;code&gt;를 기준으로 현재 사용 중인 element 수와 확보된 buffer(버퍼) 크기를 구분하면 되기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;그런데 트리나 hash table처럼, 내부적으로 하나의 연속 buffer만으로 표현되지 않는 data structure는 이야기가 조금 다르다.&lt;br &#x2F;&gt;
이런 구조는 node(노드), bucket(버킷), 보조 배열 같은 여러 단위의 메모리를 따로 관리해야 할 것 같은데, 실제로는 어떤 식으로 할당과 해제가 이루어지는지 잘 감이 오지 않았다.&lt;&#x2F;p&gt;
&lt;p&gt;매 삽입&#x2F;삭제마다 node를 위한 메모리의 할당과 해제를 반복하는 건가?&lt;br &#x2F;&gt;
아니면 일정한 관리 단위가 따로 있는 건가? 뭐 근데 생각해보면 같은 역할이어도 구현체마다 다를 수 있을거 같긴함.&lt;&#x2F;p&gt;
&lt;p&gt;GC가 있으면 그냥 unreachable memory면 상관없는데, C는 포인터 연산에 주소 이동까지 가능해서 rc 기반의 커스텀 GC를 만들어서 추가할수도 없고, (제한된 범용 사용을 강제하면 될수도?)&lt;&#x2F;p&gt;
&lt;p&gt;그래서 이게 어떻게 관리되는가...&lt;&#x2F;p&gt;
&lt;h4 id=&quot;josa-1&quot;&gt;조사&lt;&#x2F;h4&gt;
&lt;p&gt;AI와 실제 공식문서, 코드 약간 참고(전부는 아님)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;C 범용 자료구조 라이브러리의 data structure 내부 메모리 관리 방식&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;contiguous buffer 기반&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;내부에 연속 메모리 buffer를 하나 두고 관리&lt;&#x2F;li&gt;
&lt;li&gt;보통 &lt;code&gt;size&lt;&#x2F;code&gt;, &lt;code&gt;capacity&lt;&#x2F;code&gt; 개념이 있음&lt;&#x2F;li&gt;
&lt;li&gt;배열 기반 data structure가 대표적임&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;node 기반&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;element 하나당 node 하나를 두는 방식&lt;&#x2F;li&gt;
&lt;li&gt;삽입 시 node 단위로 할당, 삭제 시 node 단위로 해제&lt;&#x2F;li&gt;
&lt;li&gt;linked list, tree 같은 구조가 여기에 해당&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;buffer + node 혼합형&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;내부에 bucket&#x2F;slot 배열 같은 연속 메모리를 두면서도&lt;&#x2F;li&gt;
&lt;li&gt;구현 방식에 따라 별도 entry(엔트리)&#x2F;node를 함께 관리할 수 있음&lt;&#x2F;li&gt;
&lt;li&gt;hash table이 대표적임&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;custom allocator &#x2F; memory pool 사용 가능&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;무조건 일반 &lt;code&gt;malloc&#x2F;free&lt;&#x2F;code&gt;만 쓰는 건 아님&lt;&#x2F;li&gt;
&lt;li&gt;라이브러리에 따라 allocator를 교체하거나 pool을 붙일 수 있음&lt;&#x2F;li&gt;
&lt;li&gt;Collections-C는 memory pool을 별도 기능으로 제공하고, list 같은 data structure의 allocator를 pool allocator로 바꾸는 예제도 README에 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;자료구조별로 보면&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;배열 기반 data structure&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;비교적 단순함&lt;&#x2F;li&gt;
&lt;li&gt;내부 buffer를 들고 있다가 capacity가 부족하면 재할당&lt;&#x2F;li&gt;
&lt;li&gt;value-copy &#x2F; pointer container 둘 다 제공하는 경우 많음&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;linked list&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;비연속 메모리 기반이지만 구조 자체는 비교적 단순한 편&lt;&#x2F;li&gt;
&lt;li&gt;list 본체와 각 node가 분리되어 있고&lt;&#x2F;li&gt;
&lt;li&gt;삽입&#x2F;삭제 시 node 단위 할당&#x2F;해제가 일어남&lt;&#x2F;li&gt;
&lt;li&gt;다만 저장되는 payload 자체는 보통 포인터라서, 메모리 배치 기준으로는 node 기반이고, element 저장 방식 기준으로는 pointer container인 경우가 많음&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;tree&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;이것도 node 기반 (node 단위 할당&#x2F;해제)&lt;&#x2F;li&gt;
&lt;li&gt;linked list보다 삭제&#x2F;재연결 쪽이 더 복잡함&lt;&#x2F;li&gt;
&lt;li&gt;저장 방식 기준으로는 key&#x2F;value를 &lt;code&gt;void *&lt;&#x2F;code&gt;나 포인터로 다루는 pointer container 계열이 많음&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;hash table&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;구현에 따라 차이가 큼&lt;&#x2F;li&gt;
&lt;li&gt;open addressing이면 slot 배열 같은 연속 메모리 중심으로 관리할 수 있음&lt;&#x2F;li&gt;
&lt;li&gt;chaining이면 bucket 배열 + 체인용 node 구조가 섞일 수 있음&lt;&#x2F;li&gt;
&lt;li&gt;따라서 내부 메모리 관리 기준으로는 contiguous buffer 성격과 node 성격이 섞일 수 있고, element 저장 방식 기준으로는 보통 key&#x2F;value 포인터를 저장하는 pointer container에 가깝다&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;실제 non-contiguous &#x2F; node 기반 자료구조를 라이브러리별로 보면&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GLib&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GSList&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;GList&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;GQueue&lt;&#x2F;code&gt;: list 계열이고, data 포인터를 저장하므로 &lt;strong&gt;node 기반 + pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;GTree&lt;&#x2F;code&gt;: balanced tree 기반의 key&#x2F;value container라서 &lt;strong&gt;node 기반 + pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;GHashTable&lt;&#x2F;code&gt;: key&#x2F;value를 복사하지 않으므로 API 기준으로는 &lt;strong&gt;pointer container&lt;&#x2F;strong&gt;. 다만 내부 구현까지 단순 node 기반이라고 하긴 애매함&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;c-algorithms&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;라이브러리 전반이 &lt;code&gt;void *&lt;&#x2F;code&gt; 기반이라 모두 &lt;strong&gt;pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;list.h&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;slist.h&lt;&#x2F;code&gt;: &lt;strong&gt;node 기반 + pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;avl-tree.h&lt;&#x2F;code&gt;: &lt;strong&gt;node 기반 + pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;hash-table.h&lt;&#x2F;code&gt;: key&#x2F;value가 &lt;code&gt;void *&lt;&#x2F;code&gt;이고 free function 등록도 가능해서, &lt;strong&gt;pointer container + free callback 연결 가능&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Collections-C&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;README에서 pointer container와 sized container를 분리함&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;CC_List&lt;&#x2F;code&gt;, &lt;code&gt;CC_SList&lt;&#x2F;code&gt;, &lt;code&gt;CC_HashTable&lt;&#x2F;code&gt;, &lt;code&gt;CC_TreeTable&lt;&#x2F;code&gt; 등은 &lt;strong&gt;pointer container&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;이 중 리스트&#x2F;트리 계열은 자연스럽게 &lt;strong&gt;node 기반 + pointer container&lt;&#x2F;strong&gt;로 볼 수 있음&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;대충 보면&lt;&#x2F;strong&gt; - (사실 상 다 pointer container라고 봄.)&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;non-contiguous &#x2F; node 기반 자료구조는 대부분 pointer container&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;GLib의 &lt;code&gt;GList&lt;&#x2F;code&gt;, &lt;code&gt;GSList&lt;&#x2F;code&gt;, &lt;code&gt;GTree&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;c-algorithms의 linked list, AVL tree&lt;&#x2F;li&gt;
&lt;li&gt;Collections-C의 &lt;code&gt;CC_List&lt;&#x2F;code&gt;, &lt;code&gt;CC_SList&lt;&#x2F;code&gt;, &lt;code&gt;CC_TreeTable&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;value-copy container는 주로 contiguous array 쪽에 몰려 있음&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;GLib의 &lt;code&gt;GArray&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Collections-C의 &lt;code&gt;CC_ArraySized&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;hash table은 내부 메모리 관리 방식은 구현 따라 달라도, 외부 API 기준으로는 대체로 pointer container&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;key&#x2F;value를 복사하지 않고 포인터나 &lt;code&gt;void *&lt;&#x2F;code&gt;를 저장하는 경우가 많음&lt;&#x2F;li&gt;
&lt;li&gt;대신 destroy&#x2F;free callback이나 free-all 계열 API를 붙여서 element 정리를 연결하는 방식이 흔함.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;jeongri-1&quot;&gt;정리&lt;&#x2F;h4&gt;
&lt;p&gt;대충 보면 contiguous 쪽은 value-copy &#x2F; pointer container 둘 다 만들기 쉬운 반면, non-contiguous &#x2F; node 기반 자료구조는 범용 라이브러리에서 대부분 pointer container로 제공된다.&lt;&#x2F;p&gt;
&lt;p&gt;이게 불가능해서라기보다는, generic C 라이브러리에서 value-copy 방식으로 만들었을 때 애매한 점이 많기 때문인 듯함.&lt;&#x2F;p&gt;
&lt;p&gt;삽입&#x2F;삭제 자체만 보면 node 기반도 value-copy가 불가능한 건 아니다.&lt;br &#x2F;&gt;
node마다 값을 직접 넣고, 삽입 시 복사하고, 삭제 시 그 node를 해제하면 되니까 구현 자체는 가능함.&lt;br &#x2F;&gt;
그리고 한 번 들어간 뒤의 재연결이나 이동은 보통 node 포인터만 바꾸면 되므로, 그 과정에서 값 복사가 계속 일어나는 것도 아님.&lt;&#x2F;p&gt;
&lt;p&gt;근데 조회와 반환 쪽에서 문제가 있다.&lt;&#x2F;p&gt;
&lt;p&gt;contiguous 쪽은 내부가 연속된 buffer라서 특정 위치만 알면 곧바로 접근할 수 있다.&lt;br &#x2F;&gt;
즉 value-copy를 하더라도 “연속된 저장소에 값을 복사해 넣고, offset으로 다시 접근한다”는 모델이 비교적 단순하다.&lt;&#x2F;p&gt;
&lt;p&gt;반면 non-contiguous &#x2F; node 기반은 node 안에 값을 직접 저장한다고 해도, 그 값을 사용자에게 어떻게 돌려줄지가 애매하다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;포인터로 넘겨주기&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;node 내부 값의 주소를 넘겨주면 되긴 함&lt;&#x2F;li&gt;
&lt;li&gt;근데 그러면 결국 사용자 입장에서는 포인터를 받아 쓰게 되므로, pointer container와 체감상 큰 차이가 줄어듦&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;값을 복사해서 넘겨주기&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;shallow copy면 값 안에 포인터가 있을 때 문제가 그대로 남음&lt;&#x2F;li&gt;
&lt;li&gt;deep copy면 복사 비용, 버퍼 관리, 타입별 정책 문제가 생김&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;즉 node 기반 value-copy container의 핵심 문제는 “삽입이 어렵다”가 아니라, &lt;strong&gt;generic한 조회&#x2F;반환 API를 깔끔하게 만들기 어렵다&lt;&#x2F;strong&gt;는 쪽에 더 가까움.&lt;&#x2F;p&gt;
&lt;p&gt;게다가 non-contiguous &#x2F; node 기반 자료구조는 원래도 node마다 포인터 필드 같은 오버헤드가 붙고, allocation&#x2F;free가 자주 일어나고, cache locality도 좋지 않은 편이다.&lt;br &#x2F;&gt;
그런데 여기에 value-copy 기반 API까지 얹으면 복사&#x2F;반환 규칙까지 더 복잡해진다. (반대로 &lt;code&gt;GArray&lt;&#x2F;code&gt;는 반환에서 memcpy같은 복사가 일어나지만, capacity가 충분하면 추가에서 할당이 일어나지 않고 매모리와 캐시 효율이 좋다.)&lt;br &#x2F;&gt;
반면 &lt;code&gt;void *&lt;&#x2F;code&gt;를 저장하는 pointer container는 구현도 단순하고, list &#x2F; tree &#x2F; hash table 전반에 공통적으로 적용하기도 쉽다.&lt;&#x2F;p&gt;
&lt;p&gt;그래서 node 기반 data structure에서도 value-copy 방식 자체는 가능하지만, 적어도 범용 C 라이브러리에서는 이런 특별한 사용 예시를 지원하지 않는 것 같다.&lt;br &#x2F;&gt;
아마 그런 이유로 GLib, c-algorithms, Collections-C 같은 라이브러리들도 non-contiguous &#x2F; node 기반 자료구조는 다 pointer container 쪽으로 제공하는 것 같음.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;custom-allocator-memory-pool-eul-sayonghaneun-iyu&quot;&gt;custom allocator &#x2F; memory pool 을 사용하는 이유&lt;&#x2F;h2&gt;
&lt;p&gt;기본적으로 C 자료구조 구현은 내부 메모리를 malloc&#x2F;free로 직접 관리하는 경우가 많다.&lt;br &#x2F;&gt;
하지만 자료구조의 특성에 따라 allocation 패턴이 매우 자주 반복되거나, 작은 크기의 메모리를 대량으로 다루게 되면 일반 힙 할당만으로는 비효율적일 수 있다.&lt;br &#x2F;&gt;
이럴 때 custom allocator나 memory pool을 붙여 내부 메모리 관리 방식을 바꾸기도 한다.&lt;&#x2F;p&gt;
&lt;p&gt;대표적으로 linked list, tree, chaining 기반 hash table처럼 node 단위 할당&#x2F;해제가 자주 발생하는 자료구조에서 의미가 크다.&lt;&#x2F;p&gt;
&lt;p&gt;memory pool은 이런 node들을 위해 미리 큰 메모리 덩어리를 확보해 두고, 그 안에서 같은 크기의 node를 재사용하는 방식으로 동작할 수 있다.&lt;br &#x2F;&gt;
이 경우 매번 운영체제&#x2F;일반 힙에 직접 요청하지 않고 pool 내부에서 빠르게 꺼내고 반납할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;간단한 예시&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; 이렇게 pool을 미리 할당해서 node 추가&#x2F;삭제 시 할당이 발생하지 않게 한다.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; POOL_COUNT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; Node {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    void *&lt;&#x2F;span&gt;&lt;span&gt;data;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    struct&lt;&#x2F;span&gt;&lt;span&gt; Node &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;next;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} Node;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; NodePool {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Node &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;[POOL_COUNT];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Node &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;free_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} NodePool;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Node 할당
&lt;ul&gt;
&lt;li&gt;평소: malloc(sizeof(Node))&lt;&#x2F;li&gt;
&lt;li&gt;pool 사용: pool_alloc(pool) → pool 안에서 Node 하나 꺼냄&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;free
&lt;ul&gt;
&lt;li&gt;평소: free(node)&lt;&#x2F;li&gt;
&lt;li&gt;pool 사용: pool_free(pool, node) → OS에 반납 안 하고 pool의 빈 칸 목록으로 되돌림&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;사용 시 장점&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;작은 객체의 반복 할당&#x2F;해제 비용 감소
&lt;ul&gt;
&lt;li&gt;node 기반 자료구조에서는 작은 크기의 allocation이 매우 자주 일어날 수 있다.&lt;&#x2F;li&gt;
&lt;li&gt;pool을 쓰면 이런 비용을 줄이기 쉽다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;fragmentation 완화 가능
&lt;ul&gt;
&lt;li&gt;같은 크기의 node를 반복적으로 관리하면 일반 힙보다 메모리 배치가 단순해질 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;allocation 패턴 제어
&lt;ul&gt;
&lt;li&gt;자료구조 내부 메모리를 어떤 방식으로 확보하고 반납할지 구현자가 통제하기 쉬워진다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;같은 수명의 메모리 묶음 관리
&lt;ul&gt;
&lt;li&gt;arena&#x2F;pool 계열 allocator를 쓰면 특정 자료구조 인스턴스와 함께 내부 메모리를 한꺼번에 정리하는 전략도 가능하다.
&lt;strong&gt;사용 시 단점&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;pool 고갈 처리 필요&lt;&#x2F;li&gt;
&lt;li&gt;variable-size payload에는 사용 불가능&lt;&#x2F;li&gt;
&lt;li&gt;요소의 free 순서&#x2F;소유권 문제는 여전함 (메모리풀은 node의 메모리 관리 문제만 보완해줌.)&lt;&#x2F;li&gt;
&lt;li&gt;디버깅이 더 까다로울 수 있음 (실제로는 사용하는 상태라 use-after-free 문제를 OS나 분석 툴이 잡기 어려움)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;daepyojeogin-c-jaryogujo-raibeureori-kodeu-bunseoghagi&quot;&gt;대표적인 C 자료구조 라이브러리 코드 분석하기&lt;&#x2F;h2&gt;
&lt;p&gt;편의를 위해 GLib는 Gitlab에서 관리되지만, Github에 있는 미러 레포지토리로 봄.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;glib-garray&quot;&gt;GLib - &lt;code&gt;GArray&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;garray.h#L38-L59&quot;&gt;&lt;code&gt;garray.h&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;는 배열 관련 타입을 선언하는데, 헤더에선 최소한으로 노출하고,&lt;&#x2F;p&gt;
&lt;p&gt;실제 구현하는 구조체는 &lt;code&gt;GRealArray&lt;&#x2F;code&gt;, &lt;code&gt;GRealPtrArray&lt;&#x2F;code&gt; 같은 구조체를 쓴다. 여기에는 더 많은 필드가 내부에 들어있음.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;garray.c#L52-L73&quot;&gt;예시&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; garray.h - https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;garray.h#L38-L59&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; _GArray&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  gchar &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;data;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint len;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; garray.c - https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;garray.c#L52-L73&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; _GRealArray&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint8 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;data;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint   len;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint   elt_capacity;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint   elt_size;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint   zero_terminated : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  guint   clear : &lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  gatomicrefcount ref_count;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  GDestroyNotify clear_func;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;garray.h#L69&quot;&gt;인덱스 접근인 &lt;code&gt;g_array_index(a,t,i)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;의 경우 매크로로, 내부적으론 일반적인 배열의 접근과 동일하다. 따라서 해당 키워드로 수정과 조회가 다 가능하다.&lt;&#x2F;p&gt;
&lt;p&gt;포인터가 아니므로 변수에 받는 순간 값 복사가 일어난다. 따라서 그 복사본을 수정해도 배열 원본에는 반영되지 않는다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; 정의&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; g_array_index&lt;&#x2F;span&gt;&lt;span&gt;(a,t,i)      (((t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;) (a)-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;) [(i)])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; 사용 예&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Foo x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; g_array_index&lt;&#x2F;span&gt;&lt;span&gt;(arr, Foo,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;g_array_index&lt;&#x2F;span&gt;&lt;span&gt;(arr, Foo,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; new_value;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;2가지 삭제 연산을 제공하는데,
일반적으론 &lt;code&gt;memmove()&lt;&#x2F;code&gt;로 메모리를 이동함.  (예: &lt;code&gt;g_array_remove_index()&lt;&#x2F;code&gt;). &lt;code&gt;g_array_remove_index_fast()&lt;&#x2F;code&gt;는 빠른 삭제로 마지막 원소를 삭제 위치에 &lt;code&gt;memcpy()&lt;&#x2F;code&gt;로 덮어씀. 빠르지만 순서가 바뀜.&lt;&#x2F;p&gt;
&lt;p&gt;그 외에는 append, insert, update 류 연산을 제공하는데, 알고있는것과 크게 다르지 않음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;glib-gptrarray&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gtk.org&#x2F;glib&#x2F;struct.PtrArray.html&quot;&gt;GLib - &lt;code&gt;GPtrArray&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;GArray&lt;&#x2F;code&gt;와 유사하지만, 포인터를 저장하기 위한 배열. 포인터를 위한 여러 편의 기능을 제공한다.&lt;&#x2F;p&gt;
&lt;p&gt;말했던 destroy callback 함수 중 하나인 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gtk.org&#x2F;glib&#x2F;type_func.PtrArray.set_free_func.html&quot;&gt;&lt;code&gt;g_ptr_array_set_free_func()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;code&gt;g_ptr_array_steal()&lt;&#x2F;code&gt;는 노드를 삭제하지만 free callback를 호출하지 않고 호출자에게 포인터의 소유권을 넘긴다.&lt;br &#x2F;&gt;
&lt;code&gt;g_ptr_array_new_null_terminated()&lt;&#x2F;code&gt;는ㄴ len과 별개로 끝에 NULL 센티넬을 유지하게 하는 생성자다.&lt;&#x2F;p&gt;
&lt;p&gt;실제로 쓰기 위한 설명은 아니니 이정도로만 찾아봄.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;glib-glist-or-gslist&quot;&gt;GLib - &lt;code&gt;GList&lt;&#x2F;code&gt; or &lt;code&gt;GSList&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;GList&lt;&#x2F;code&gt;는 내부 구조를 숨기지 않고 그대로 사용한다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; glist.h - https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;glist.h#L39-L46&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; _GList&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  gpointer data;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  GList &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;next;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  GList &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;prev;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;특이한게 &lt;code&gt;len&lt;&#x2F;code&gt;이나 별도 정보를 저장하는 컨테이너가 없고, 노드 하나가 리스트의 일부인 형태다.&lt;&#x2F;p&gt;
&lt;p&gt;다음과 같은 주의사항을 공식문서에서도 명시한다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The doubly-linked list does not keep track of the number of items and does not keep track of both the start and end of the list. If you want fast access to both the start and the end of the list, and&#x2F;or the number of items in the list, use a GQueue instead.&lt;br &#x2F;&gt;
이중 연결 리스트는 항목의 개수를 저장하지 않으며, 리스트의 시작과 끝 위치도 저장하지 않습니다. 리스트의 시작과 끝 위치, 그리고 항목 개수에 빠르게 접근해야 한다면 GQueue 를 사용하는 것이 좋습니다.&lt;&#x2F;p&gt;
&lt;p&gt;Note that most of the GList functions expect to be passed a pointer to the first element in the list. The functions which insert elements return the new start of the list, which may have changed.&lt;br &#x2F;&gt;
GList 함수 대부분은 리스트의 첫 번째 요소에 대한 포인터를 인수로 받는다는 점에 유의하십시오. 요소를 삽입하는 함수는 리스트의 새로운 시작 위치를 반환하는데, 이 위치는 변경될 수 있습니다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gtk.org&#x2F;glib&#x2F;data-structures.html#doubly-linked-lists&quot;&gt;doubly-linked-lists - 공식문서&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;따라서 빈 리스트인 경우 &lt;code&gt;NULL&lt;&#x2F;code&gt;이고, 연산의 결과로 head가 바뀔 수 있다. (리스트 구조가 바뀔 수 있는 연산은 대체로 &lt;code&gt;GList *&lt;&#x2F;code&gt;를 반환하고, 그 반환값은 보통 처리 결과 리스트의 head라고 함.)&lt;&#x2F;p&gt;
&lt;p&gt;제거는 2종류인데, &lt;code&gt;g_list_remove_link()&lt;&#x2F;code&gt;는 연결만 끊고 노드는 살려두고, &lt;code&gt;g_list_remove()&lt;&#x2F;code&gt;는 노드까지 해제한다.&lt;br &#x2F;&gt;
단, 둘 다 각 요소 data까지 free하지는 않으므로 직접 처리해야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;노드의 추가&#x2F;삭제에 따라서 노드의 할당과 해제가 발생하는 걸 볼 수 있다.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;glist.c#L166-L221&quot;&gt;&lt;code&gt;g_list_append()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;는 매크로나 여러 흐름을 타고 들어가면 최종적으로 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;gslice.c#L171-L197&quot;&gt;&lt;code&gt;g_slice_alloc()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;를 호출한다.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;glist.c#L494-L525&quot;&gt;&lt;code&gt;g_list_remove()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;는 free 하는 함수를 호출한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;GSList&lt;&#x2F;code&gt;는 Singly Linked List로, 그 외의 특징은 동일하므로 생략.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;glib-ghashtable&quot;&gt;GLib - &lt;code&gt;GHashTable&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;GHashTable&lt;&#x2F;code&gt;는 open addressing 기반으로 구성되어 contiguous한 container(여기선 slot이라고 더 많이 부름)를 가진다.&lt;br &#x2F;&gt;
이런 구조가 가능한 이유는 각 slot이 key&#x2F;value 객체 본체가 아니라 pointer 표현을 저장하기 때문이다. 따라서 내부 저장소는 고정 크기 slot들의 배열로 관리된다.&lt;&#x2F;p&gt;
&lt;p&gt;즉, &lt;code&gt;GHashTable&lt;&#x2F;code&gt;은 pointer 기반 container이며, key&#x2F;value가 가리키는 실제 객체의 생명주기는 별도로 관리된다.&lt;br &#x2F;&gt;
필요하면 &lt;code&gt;g_hash_table_new_full()&lt;&#x2F;code&gt; 등으로 destroy callback을 등록해 remove&#x2F;destroy 시 pointee 정리를 연결할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;ghash.c#L212-L240&quot;&gt;&lt;code&gt;_GHashTable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; 정의를 보면, &lt;code&gt;keys&lt;&#x2F;code&gt;, &lt;code&gt;values&lt;&#x2F;code&gt;, &lt;code&gt;hashes&lt;&#x2F;code&gt; 배열로 구성된다.&lt;br &#x2F;&gt;
&lt;code&gt;hashes[i]&lt;&#x2F;code&gt;는 해당 slot의 상태 또는 hash 값(또는 UNUSED&#x2F;TOMBSTONE 상태)을 저장하고, &lt;code&gt;keys[i]&lt;&#x2F;code&gt;와 &lt;code&gt;values[i]&lt;&#x2F;code&gt;는 그 slot의 key&#x2F;value 표현을 저장한다.&lt;&#x2F;p&gt;
&lt;p&gt;keys&#x2F;values의 경우 포인터 크기(&lt;code&gt;gpointer&lt;&#x2F;code&gt;)를 가지므로, 포인터 크기 이내의 값은 slot에 직접 저장하는 식으로 최적화 할 수 있다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gtk.org&#x2F;glib&#x2F;conversion-macros.html#gint-to-pointer&quot;&gt;&lt;code&gt;GINT_TO_POINTER&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; 매크로를 사용한다. (이 때는 value에선 값이 저장된다고 볼 수도 있겠다.)&lt;&#x2F;p&gt;
&lt;p&gt;아래는 메모리와 별개지만 내부 해시 충돌 처리 로직이 궁금해서 찾아봄.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GNOME&#x2F;glib&#x2F;blob&#x2F;2.88.0&#x2F;glib&#x2F;ghash.c#L418-L475&quot;&gt;&lt;code&gt;g_hash_table_lookup_node()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;위에서 open addressing + tombstone 방식으로 구현되어있다고 말했다.&lt;&#x2F;p&gt;
&lt;p&gt;따라서 probe(충돌로 다음 버킷을 구하는 과정)이 여러 번 발생할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;충돌나면 넘기다가 첫 tombstone을 만나면 기록해두고, key에 맞는 node를 못 찾으면 할당한다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UNUSED&lt;&#x2F;code&gt;: 한 번도 안 쓴 빈 칸&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;TOMBSTONE&lt;&#x2F;code&gt;: 예전에 썼다가 삭제된 칸&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;REAL HASH&lt;&#x2F;code&gt;: 현재 원소가 들어 있는 칸&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;리사이즈 판단에는 &lt;code&gt;noccupied&lt;&#x2F;code&gt;를 쓰는데, 이는 &lt;code&gt;nnodes&lt;&#x2F;code&gt;(REAL HASH 엔트리 수) + &lt;code&gt;tombstone&lt;&#x2F;code&gt; 수이다.&lt;br &#x2F;&gt;
(사이즈 확장 기준은 0.94 이상 일 때인데, Separate Chaining 방식 대비 더 작음. 이건 1 이상도 가능)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;collections-c-list-hash-table&quot;&gt;Collections-C - &lt;code&gt;list&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;hash table&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;(Glib만 봐도 충분히 공통점이 보여서 다음 내용은 AI 답변을 정리하고 대충 확인만 했다.)&lt;&#x2F;p&gt;
&lt;p&gt;Collections-C도 전반적으로 pointer container 중심이다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;srdja&#x2F;Collections-C&#x2F;blob&#x2F;master&#x2F;src&#x2F;cc_list.c&quot;&gt;&lt;code&gt;CC_List&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;는 node 기반 리스트이고, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;srdja&#x2F;Collections-C&#x2F;blob&#x2F;master&#x2F;src&#x2F;cc_hashtable.c&quot;&gt;&lt;code&gt;CC_HashTable&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;도 key&#x2F;value 포인터를 저장하는 형태라 원소 수명 관리는 호출자가 의식해야 한다.&lt;br &#x2F;&gt;
대신 &lt;code&gt;destroy_free&lt;&#x2F;code&gt;, &lt;code&gt;remove_all_free&lt;&#x2F;code&gt; 같은 free-all 계열 API와 memory pool 활용 여지가 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;c-algorithms-list-avl-hash&quot;&gt;c-algorithms - &lt;code&gt;list&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;avl&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;hash&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;(Glib만 봐도 충분히 공통점이 보여서 다음 내용은 AI 답변을 정리하고 대충 확인만 했다.)&lt;&#x2F;p&gt;
&lt;p&gt;c-algorithms는 라이브러리 전반이 &lt;code&gt;void *&lt;&#x2F;code&gt; 기반 pointer container다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fragglet&#x2F;c-algorithms&#x2F;blob&#x2F;master&#x2F;src&#x2F;list.c&quot;&gt;&lt;code&gt;list&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;와 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fragglet&#x2F;c-algorithms&#x2F;blob&#x2F;master&#x2F;src&#x2F;avl-tree.c&quot;&gt;&lt;code&gt;avl&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;은 node 기반 자료구조이고, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fragglet&#x2F;c-algorithms&#x2F;blob&#x2F;master&#x2F;src&#x2F;hash-table.c&quot;&gt;&lt;code&gt;hash&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;도 key&#x2F;value 포인터 저장형이며 일부 구조에서는 free callback으로 정리 동작을 연결할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fragglet&#x2F;c-algorithms&#x2F;blob&#x2F;master&#x2F;src&#x2F;arraylist.c&quot;&gt;&lt;code&gt;arraylist&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;도 있는데, 이건 Glib의 &lt;code&gt;GPtrArray&lt;&#x2F;code&gt;와 비슷하게 포인터를 저장하는 배열이다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Tsoding 유튜브의 C관련 내용 정리</title>
          <pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-tsoding-1st/</link>
          <guid>https://sijun-yang.com/jungle/jungle-tsoding-1st/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-tsoding-1st/">&lt;p&gt;C 자료구조 공부를 하려고 자료를 찾아보다가, 예전부터 이름만 알고 있던 Tsoding 영상을 몇 개 보게 됐다.&lt;&#x2F;p&gt;
&lt;p&gt;C를 쓰다보면 필요한 유용한 정보들이 많아서 메모해두려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;항상 아쉬운점은 Tsoding Daily 채널의 영상의 자막은 트위치 댓글을 보여주는 자막이라서, 자동 생성 자막을 봐야할 때가 있다.&lt;&#x2F;p&gt;
&lt;p&gt;영어권 사용자에게는 큰 문제가 아닐 수 있지만, 영어를 못하는 사람에게는 꽤나 불편함;;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jeongrineun-anhago-ringkeuman-jeogeulgeo&quot;&gt;정리는 안하고 링크만 적을거&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;sFYFuBzu9Ow?si=dUHLVEkJvBLUAGL3&quot;&gt;Why Linux Has This Syscall?!&lt;&#x2F;a&gt;: mmap 시스템 콜에 대한 사용 영상&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;sZ8GJ1TiMdk?si=TKc46RBQc5PDPi5t&quot;&gt;Writing My Own Malloc in C&lt;&#x2F;a&gt;: 직접 Malloc 구현하는 영상&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;thread 생성이나, gblic의 malloc에서도 mmap를 사용하니까 봐두면 좋지 않을까... (관련 자료: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2023&#x2F;03&#x2F;23&#x2F;&quot;&gt;Practical libc-free threading on Linux&lt;&#x2F;a&gt; )&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-dynamic-arrays-in-c&quot;&gt;1. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;95M6V3mZgrI?si=Hl2A0gCh8QeK3TZC&quot;&gt;Dynamic Arrays in C&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Dynamic Arrays를 사용하는 방법을 소개한다.&lt;&#x2F;p&gt;
&lt;p&gt;count와 capacity를 구조체로 묶어두면 동적 배열의 상태를 한 번에 관리할 수 있다. 이런 식으로 &lt;code&gt;items&lt;&#x2F;code&gt;, &lt;code&gt;count&lt;&#x2F;code&gt;, &lt;code&gt;capacity&lt;&#x2F;code&gt; 패턴을 공통화해두면, 필요할 경우 매크로나 별도 래퍼를 이용해 다른 타입에도 같은 방식으로 확장할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;구조 자체는 &lt;code&gt;count&lt;&#x2F;code&gt;와 &lt;code&gt;capacity&lt;&#x2F;code&gt;를 비교해서 확장하는 연산으로 평범함.&lt;&#x2F;p&gt;
&lt;p&gt;예를 들어 int 대신 float를 저장하는 구조체를 따로 만들고 같은 로직을 적용(매크로를 사용해서 재사용)하면, 동일한 방식의 동적 배열을 다른 타입에도 사용할 수 있다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#include &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;typedef struct {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    int *items;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    size_t count;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    size_t capacity;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;} Numbers;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;int main(void)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Numbers xs = {0};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for (int x = 0; x &amp;lt; 10; ++x) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        if (xs.count == xs.capacity) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            xs.capacity = (xs.capacity == 0) ? 4 : xs.capacity * 2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            xs.items = realloc(xs.items, xs.capacity * sizeof(*xs.items));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        xs.items[xs.count++] = x;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for (size_t i = 0; i &amp;lt; xs.count; ++i) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        printf(&amp;quot;%d\n&amp;quot;, xs.items[i]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    free(xs.items);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return 0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;2-libraries-that-quietly-revolutionized-c&quot;&gt;2. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;kS_GqDp6IT4?si=7yUhiCaoXcy0UhWo&quot;&gt;Libraries That Quietly Revolutionized C&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nothings&#x2F;stb&quot;&gt;STB&lt;&#x2F;a&gt; 스타일의 &lt;strong&gt;single-file library&lt;&#x2F;strong&gt; 를 소개하는데, C의 불편함을 정면으로 부정하는 대신 오히려 &lt;strong&gt;C의 전처리기와 번역 단위 모델을 이용해서 단순한 배포 형식&lt;&#x2F;strong&gt;을 만든 사례를 설명한다.&lt;&#x2F;p&gt;
&lt;p&gt;라이브러리를 헤더&#x2F;소스 여러 파일로 쪼개지 않고 &lt;strong&gt;하나의 헤더 파일로 배포&lt;&#x2F;strong&gt;한다. 그리고 특정 &lt;code&gt;.c&lt;&#x2F;code&gt; 파일 한 곳에서만 &lt;code&gt;STB_IMAGE_IMPLEMENTATION&lt;&#x2F;code&gt; 같은 매크로를 정의해 실제 구현을 끌어오고, 나머지 곳에서는 선언만 보이게 만든다. 이 방식은 C의 &lt;code&gt;#include&lt;&#x2F;code&gt; 가 사실상 텍스트 복사라는 점, 선언과 정의를 분리해야 하는 컴파일 모델을 정확히 이용한 패턴이다.&lt;&#x2F;p&gt;
&lt;p&gt;STB 스타일 single-file 라이브러리는 C를 더 편한 언어로 바꾼 것이 아니라, C의 전처리기와 번역 단위 모델을 활용해 배포를 단순화한 패턴이다. 사용자는 헤더 하나만 포함해 쉽게 시작할 수 있고, 필요하면 구현을 별도 번역 단위에서 컴파일해 정적 라이브러리처럼 연결할 수도 있다.&lt;&#x2F;p&gt;
&lt;p&gt;또 하나 인상적인 지점은 “single-file”이 꼭 작은 코드라는 뜻은 아니라는 점이다. 영상에서는 MiniAudio 같은 큰 라이브러리도 예시로 언급되는데, 이건 단일 파일 배포가 단순히 취미성 트릭이 아니라 &lt;strong&gt;배포와 통합 비용을 최소화하는 실용적 설계&lt;&#x2F;strong&gt;라는 걸 보여준다.&lt;br &#x2F;&gt;
npm 같은 무거운 의존성 생태계와 대비해서 보면, C 진영이 아직도 특정 종류의 단순함에서는 매우 강하다는 얘기이기도 하다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-how-to-prevent-all-memory-leaks&quot;&gt;3. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;bzBU7iF2Rms?si=04HzKRkX5fAb-UW6&quot;&gt;How to Prevent All Memory Leaks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;메모리 할당&#x2F;해제는 추상화된 개념임. 따라서 메모리 Leak을 정의하기 어렵고 잡기도 어려움.&lt;&#x2F;p&gt;
&lt;p&gt;free를 안하고 프로그램이 끝나면서 지워지는게 문제는 아님. 의도하지 않게 free가 안되는게 Leak임.&lt;&#x2F;p&gt;
&lt;p&gt;GC가 있다고 해도 이런 문제는 생길 수 있음(reference cycle). 특히 C같은 시스템 언어에선 포인터 연산이 가능해서 unreachable memory 모델이 유효하지 않을 때도 있음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-yoyag&quot;&gt;AI 요약&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;1. Valgrind와 ASan은 둘 다 쓴다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding은 메모리 릭을 잡을 때 둘 다 쓴다고 말한다. 다만 Valgrind로 메모리 릭을 잡는 건 어렵다고 본다. 이유는 “메모리 릭” 자체의 정의가 흐리기 때문이라고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. “종료 전까지 free 안 된 메모리”라는 정의는 별로 유용하지 않다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
프로그램이 실행 내내 일정한 메모리를 잡고 있다가 종료 시점까지 해제하지 않는 경우가 흔하고, 이런 건 기술적으로는 릭처럼 보일 수 있어도 실제 문제를 일으키지 않을 수 있다고 말한다. 그래서 이 정의는 실질적으로 쓸모없다고 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. “도달 불가능한 메모리”라는 정의가 더 낫지만, 이것도 완전하지 않다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
GC 관점에서 unreachable memory라는 정의가 더 낫다고 말한다. 하지만 시스템 언어처럼 포인터를 직접 다루는 경우에는 이것도 문제가 있다. 포인터를 변형하거나 특이한 방식으로 다루면 GC가 참조를 제대로 인식하지 못할 수 있기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. D 언어의 GC 예시&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
D는 GC가 있지만 시스템 프로그래밍 언어라 포인터를 직접 다룰 수 있다. 그래서 메모리를 스캔하면서 포인터처럼 보이는 정수를 참조로 간주하는데, 포인터를 비정상적인 방식으로 조작하면 GC가 실제로는 살아 있는 객체를 unreachable하다고 오판해서 정리할 수 있다고 설명한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. XOR linked list 예시&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
XOR linked list처럼 두 포인터를 XOR해서 저장하면, 그 값은 정상적인 포인터처럼 보이지 않는다. 그래서 D의 GC는 이런 구조를 제대로 추적하지 못하고, 실제로 필요한 객체를 없애버릴 수 있다고 말한다. 그래서 D 개발자들은 이런 식의 트릭을 쓰지 말라고 권장한다고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;6. JavaScript에서도 메모리 문제는 생긴다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
JavaScript처럼 GC가 있는 언어에서도 콜백 정리를 잊으면 객체가 계속 reachable 상태로 남을 수 있다고 말한다. 즉, GC가 있어도 원래는 사라져야 할 객체가 계속 살아남아 메모리 사용량이 늘어날 수 있다는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;7. 결론: 메모리 릭은 객관적으로 딱 잘라 정의하기 어렵다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
화자는 메모리 릭이 매우 주관적이고, 깊게 생각해 보면 단순히 “free를 안 했다” 수준의 문제가 아니라고 말한다. 오히려 의도와 맥락이 섞인 애매한 개념에 가깝다고 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;8. 메모리 할당 자체가 인공적 구성물이라는 주장&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
후반부에서는 메모리 할당&#x2F;해제가 계산 모델의 본질적인 개념이라기보다, 실제 프로그래밍을 쉽게 하려고 위에 덧씌운 인공적 구조라고 말한다. 그래서 지금의 메모리 문제들은 우리가 만든 추상화 위에서 생기는 문제라고 설명한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-stop-telling-me-about-generic&quot;&gt;4. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;oEL9x6pP4FM?si=k_tPtLztFP4kuOj_&quot;&gt;Stop telling me about _Generic&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;근데 그렇게 따지면 Java의 제네릭도 제네릭이 아니라고 보는건가? 아니면 AI가 잘못 평가한건가? Java도 따지면 오버로딩 느낌인데.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-yoyag-1&quot;&gt;AI 요약&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;_Generic&lt;&#x2F;code&gt;은 generics가 아니라 타입 기반 선택기다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding은 C의 &lt;code&gt;_Generic&lt;&#x2F;code&gt;을 generics라고 부르는 건 잘못됐다고 본다. 이 기능은 전통적인 의미의 제네릭이 아니라, &lt;strong&gt;타입에 따라 이미 만들어져 있는 표현식이나 함수를 골라주는 장치&lt;&#x2F;strong&gt;에 가깝다고 말한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. 함수 오버로딩과 비교&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
C는 같은 이름에 다른 시그니처를 가진 함수를 둘 수 없지만, C++은 가능하다. 다만 내부적으로는 같은 이름을 그대로 쓰는 게 아니라, 컴파일러가 타입 정보를 이름에 섞어 넣는 &lt;strong&gt;name mangling&lt;&#x2F;strong&gt;으로 서로 다른 심볼로 구분한다고 설명한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;_Generic&lt;&#x2F;code&gt;는 오버로딩과 비슷한 구조&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding은 &lt;code&gt;_Generic&lt;&#x2F;code&gt;이 하는 일도 본질적으로는 비슷하다고 말한다. 예를 들어 &lt;code&gt;foo_int&lt;&#x2F;code&gt;, &lt;code&gt;foo_float&lt;&#x2F;code&gt;처럼 타입별 함수를 따로 만들어 두고, &lt;code&gt;_Generic&lt;&#x2F;code&gt;이 인자의 타입을 보고 그중 하나를 선택하게 하면 된다. 그래서 이 기능은 &lt;strong&gt;수동으로 mangling한 함수들 사이에서 골라주는 오버로딩 흉내&lt;&#x2F;strong&gt;일 뿐이라고 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. 핵심 차이는 dispatch와 generate의 차이다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
여기서 Tsoding은 중요한 구분을 한다. &lt;strong&gt;함수 오버로딩은 이미 존재하는 코드 중에서 어떤 것을 호출할지 결정하는 dispatch&lt;&#x2F;strong&gt;이고, &lt;strong&gt;generics는 타입에 맞는 코드를 새로 만들어내는 generate&lt;&#x2F;strong&gt;라는 것이다. 즉, 선택과 생성은 전혀 다른 문제라고 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. C++ 템플릿과 Rust generics와의 비교&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
이 차이를 설명하기 위해 C++ 템플릿과 Rust generics를 예로 든다. 둘 다 같은 함수 형태를 여러 타입으로 호출하면, 컴파일러가 타입별 버전을 실제로 따로 만들어낸다고 설명한다. 특히 Rust는 trait bound 같은 제약도 줄 수 있어서, Tsoding은 이를 더 전형적인 generics의 예로 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;6. 결론: &lt;code&gt;_Generic&lt;&#x2F;code&gt;은 진짜 generics라고 보기 어렵다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding의 결론은 단순하다. C의 &lt;code&gt;_Generic&lt;&#x2F;code&gt;은 &lt;strong&gt;타입별 코드를 생성하지 않고, 기존 코드 중 하나를 고르는 기능만 제공한다.&lt;&#x2F;strong&gt; 그래서 “C에는 이미 generics가 있다”, “&lt;code&gt;_Generic&lt;&#x2F;code&gt; 쓰면 된다” 같은 말은 부정확하다고 비판한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-you-should-read-open-source-code&quot;&gt;5. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;tBApLbmAZ6Y?si=CAP6ikHPbMZJP-yT&quot;&gt;You should read Open Source code&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;동적 라이브러리를 어떻게 사용하는데 궁금했는데, 우연히 알게 됨. 근데 이게 어떻게 접근 가능한건지는 모르곘음. 그냥 read only로 OS가 강제하고 읽어서 쓰나?&lt;br &#x2F;&gt;
그건 뭐... 나중에 알아보기&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-yoyag-2&quot;&gt;AI 요약&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;1. 결론: 구현 아이디어는 오픈소스를 읽으면서 배울 수 있다&lt;&#x2F;strong&gt; (결론을 먼저 나오게 위치 변경. 영상에서는 맨 뒤에 나옴.)&lt;br &#x2F;&gt;
Tsoding은 이런 저수준 테크닉을 어디서 배우냐는 질문에, 특별한 비법서나 강의보다 &lt;strong&gt;오픈소스 코드를 직접 읽고 디버깅하는 과정&lt;&#x2F;strong&gt;이 가장 큰 학습원이라고 말한다. 문서만 보면 지나치기 쉬운 구현상의 트릭이나 설계 의도를 실제 코드에서 더 잘 볼 수 있다는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. 이번 예시는 SDL 소스코드를 읽다가 발견한 아이디어다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
그가 소개하는 사례는 SDL2 코드를 보다가 알게 된 것이다. SDL2가 동적 라이브러리와 심볼을 다루는 방식을 따라가다 보니, &lt;code&gt;dlopen&lt;&#x2F;code&gt;과 &lt;code&gt;dlsym&lt;&#x2F;code&gt;을 이용해 꽤 흥미로운 일을 할 수 있다는 점을 발견했다고 설명한다. 즉, 이번 내용은 추상적인 개념 설명이 아니라, &lt;strong&gt;오픈소스를 읽다가 실제 구현 아이디어를 포착한 사례&lt;&#x2F;strong&gt;로 제시된다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. 기본 개념: &lt;code&gt;dlopen&lt;&#x2F;code&gt;은 런타임에 공유 라이브러리를 여는 기능이다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
먼저 Linux의 &lt;code&gt;dlopen&lt;&#x2F;code&gt;은 동적 라이브러리를 실행 중에 로드하는 기능이라고 설명한다. 보통은 &lt;code&gt;.so&lt;&#x2F;code&gt; 파일 경로를 넘겨 라이브러리를 열고, 그 결과로 핸들을 얻는다. 그리고 &lt;code&gt;dlsym&lt;&#x2F;code&gt;을 통해 그 라이브러리 안의 함수 심볼을 찾아 사용할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;dlsym&lt;&#x2F;code&gt;으로 찾은 함수는 함수 포인터로 바로 호출할 수 있다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
예를 들어 &lt;code&gt;raylib&lt;&#x2F;code&gt;를 &lt;code&gt;dlopen&lt;&#x2F;code&gt;으로 연 다음, &lt;code&gt;InitWindow&lt;&#x2F;code&gt; 같은 심볼을 &lt;code&gt;dlsym&lt;&#x2F;code&gt;으로 찾으면 그 주소를 함수 포인터로 받아 실행할 수 있다고 설명한다. 즉, 정적으로 링크하지 않았더라도, 런타임에 라이브러리를 열고 함수 주소를 찾아 실제 기능을 호출할 수 있다는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. 이런 방식은 런타임에 환경을 보고 백엔드를 고르는 데 유용하다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding은 이 메커니즘이 동적인 애플리케이션에서 유용하다고 본다. 실행 환경에 &lt;code&gt;raylib&lt;&#x2F;code&gt;가 있으면 &lt;code&gt;raylib&lt;&#x2F;code&gt;를 쓰고, 없으면 &lt;code&gt;SDL&lt;&#x2F;code&gt;을 쓰는 식으로, &lt;strong&gt;실행 시점에 무엇이 가능한지 확인한 뒤 그에 맞춰 동작을 바꿀 수 있기 때문&lt;&#x2F;strong&gt;이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;6. 여기서 재미있는 포인트는 &lt;code&gt;dlopen(NULL, ...)&lt;&#x2F;code&gt;이다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
그가 특히 흥미롭게 본 것은, &lt;code&gt;dlopen&lt;&#x2F;code&gt;에 라이브러리 경로 대신 &lt;code&gt;NULL&lt;&#x2F;code&gt;을 넣을 수 있다는 점이다. 이렇게 하면 외부 라이브러리가 아니라 &lt;strong&gt;현재 실행 중인 프로그램 자신&lt;&#x2F;strong&gt;을 열게 된다고 설명한다. 처음에는 이상하게 들리지만, 실행 파일과 공유 객체가 모두 ELF 포맷이라는 점을 생각하면 그렇게 놀랄 일은 아니라는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;7. 그러면 프로그램이 링크한 라이브러리의 심볼을 자기 자신을 통해 찾을 수 있다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
프로그램 자신을 연 뒤 &lt;code&gt;dlsym&lt;&#x2F;code&gt;을 쓰면, 현재 실행 파일이 의존하고 있는 라이브러리들의 심볼도 조회할 수 있다고 설명한다. 예를 들어 &lt;code&gt;malloc&lt;&#x2F;code&gt;을 찾아 보면, 헤더를 통해 접근한 &lt;code&gt;malloc&lt;&#x2F;code&gt;과 &lt;code&gt;dlsym&lt;&#x2F;code&gt;으로 얻은 주소가 같다는 점을 확인할 수 있다. 즉, 자기 자신을 열어도 결국 현재 프로세스가 가진 심볼 공간을 탐색하게 된다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;8. 하지만 자기 프로그램 안의 함수는 기본적으로 바로 찾을 수는 없다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Tsoding은 여기서 한 걸음 더 나아가 &lt;code&gt;main&lt;&#x2F;code&gt;도 찾을 수 있는지 시험한다. 기본 상태에서는 되지 않는다고 설명한다. 이유는 실행 파일의 자체 심볼들이 기본적으로 동적 심볼 테이블에 모두 들어가지는 않기 때문이라고 본다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;9. &lt;code&gt;-rdynamic&lt;&#x2F;code&gt;을 쓰면 자기 함수도 노출된다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
이 문제는 링크 옵션 &lt;code&gt;-rdynamic&lt;&#x2F;code&gt;으로 해결할 수 있다고 설명한다. 이 옵션을 주면 실행 파일의 심볼도 동적 심볼 테이블에 포함되므로, &lt;code&gt;dlsym&lt;&#x2F;code&gt;으로 &lt;code&gt;main&lt;&#x2F;code&gt; 같은 자기 프로그램의 함수까지 찾을 수 있다. 그리고 이렇게 얻은 주소가 실제 &lt;code&gt;main&lt;&#x2F;code&gt;의 주소와 일치한다는 점도 보여준다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;10. 심지어 &lt;code&gt;main&lt;&#x2F;code&gt;을 다시 호출할 수도 있다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
찾아낸 &lt;code&gt;main&lt;&#x2F;code&gt;을 함수 포인터처럼 호출하는 것도 가능하다고 말한다. 물론 그렇게 하면 &lt;code&gt;main&lt;&#x2F;code&gt;이 다시 자기 자신을 부르며 재귀로 들어가게 되므로 실용적이진 않다. 그래도 실행 파일도 ELF 객체라는 점을 생각하면, 기술적으로는 가능한 동작이라는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;11. SDL도 이런 기법을 실제로 활용한다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
이게 단순히 장난 같은 실험으로 끝나는 건 아니라고 설명한다. SDL2는 실제로 글로벌 심볼이나 연결된 라이브러리의 특정 심볼을 조회해서, 어떤 환경이나 드라이버가 있는지, 혹은 특정 프로그램에 대한 quirks가 필요한지 판단하는 데 이런 방식을 사용한다고 말한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;12. 더 확장하면 libffi 같은 도구로 모르는 함수도 호출할 수 있다&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
후반부에서는 &lt;code&gt;libffi&lt;&#x2F;code&gt;도 언급한다. 이 라이브러리를 쓰면 동적 라이브러리에서 찾은 함수의 시그니처를 데이터로 기술해서, 컴파일 시점에 타입을 몰라도 런타임에 올바르게 호출할 수 있다고 설명한다. Tsoding은 이를 이용해 동적 라이브러리를 불러와 함수들을 호출하는 REPL 비슷한 도구도 만들었다고 말한다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Week 05: 컴퓨팅 사고로의 전환</title>
          <pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week05/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week05/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week05/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-dp-greedy-gibon-yuhyeongeul-dab-eobsi-pul-su-isseul-jeongdoro-manhi-pulgi&quot;&gt;목표 1. DP&#x2F;Greedy 기본 유형을 답 없이 풀 수 있을 정도로 많이 풀기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 문제해결, 구현, 학습 민첩성&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;DP&#x2F;Greedy 기본 유형을 문제 기준으로 반복해서 풀고, 해설 없이 해결 가능한 범위를 넓힌다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;이번 주에는 DP&#x2F;Greedy 문제를 가능한 한 많이 풀어볼 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;많은 문제를 보고 유형을 판단하고 풀 수 있도록 빠르게 반복 학습하는 게 더 효율이 좋았고, 이번에도 동일한 전략으로 가려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;문제 파일마다 추가한 템플릿에 AI 사용 횟수&#x2F;방법, 목표 시간, 실제 시간, 초기 접근, 풀이 전략, 막힌 점을 기록한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;3&#x2F;27에 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;bdc8822077a7c96621f64175946a353c671abedb&quot;&gt;basic&lt;&#x2F;a&gt;과 난이도 하의 모든 문제를 풀었다. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;2748&quot;&gt;피보나치 수 2&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;1904&quot;&gt;01타일&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;11047&quot;&gt;동전 0&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;1541&quot;&gt;잃어버린 괄호&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;이후 난이도 중 문제에서 난도가 높아져 거의 풀지 못했고, 추가 학습과 정답 풀이를 보면서 학습하였다.&lt;&#x2F;p&gt;
&lt;p&gt;이후 난이도 하와 중 사이의 몇 문제를 추가하여 풀어보았다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;DP와 그리디는 다른 알고리즘에 비해 학습 경험이 적어서, 이전 주차의 알고리즘보다 훨씬 자주 막힌다고 느꼈다.&lt;&#x2F;p&gt;
&lt;p&gt;basic은 빠르게 끝냈지만, 난이도 중 DP에서는 아직 막히는 문제가 많았다. 지금 다시 풀어보라고 하면 절반 이상을 풀지 못할 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;비슷한 유형을 더 보충하고, 시간을 써서 여러 번 다시 푸는 과정이 더 필요해 보인다.&lt;&#x2F;p&gt;
&lt;p&gt;템플릿에 남긴 내용을 기반으로 AI에게 피드백을 요청했을 때, 다음과 같은 피드백을 받았다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;구현보다 문제 해석 + 상태 정의에서 병목이 있고, DP라면 &quot;구하는 값 &#x2F; 상태 &#x2F; 전이 &#x2F; 순회 순&quot;과 같이 DP의 구성요소에 대한 문제 정의를 명확히 하는 게 중요하다.&lt;br &#x2F;&gt;
그리디 문제는 왜 그리디로 풀 수 있는가를 명확하게 설명할 수 있을 때까지 분석이 필요하다.&lt;br &#x2F;&gt;
AI를 문제의 답이나 힌트가 아니라 사고 검증용(엣지케이스나 반례 등을 요청)으로 사용하는 것도 도움이 된다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;mogpyo-2-ai-hwalyong-bangsigeul-deo-jeoggeugjeogeuro-silheomhago-jeongrihagi&quot;&gt;목표 2. AI 활용 방식을 더 적극적으로 실험하고 정리하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: AI 활용, 협업, 학습 민첩성&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-1&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;수요코딩회나 개인 학습 과정에서도 AI를 단순 질문용으로만 쓰지 않고, 프롬프트, 에이전트, Skill을 의식적으로 실험해 볼 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;괜찮았던 방식은 혼자만 쓰고 끝내지 않고 팀원들과도 공유해 볼 생각이다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;Claude의 Agent Team을 사용해보고, Tmux 등을 사용해보았다.&lt;&#x2F;p&gt;
&lt;p&gt;Opus를 사용했는데 사용량이 너무 커서 일주일 제한에 걸렸다.&lt;&#x2F;p&gt;
&lt;p&gt;수요코딩회에서는 AI 활용 방법을 간단히 설명할 수는 있었지만, 그것이 중심이 되는 활동은 아니었다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-1&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;결과적으로 목표를 이루지 못했다. Claude의 사용량 제한으로 여러 기능을 충분히 테스트하지 못했고, 따라서 팀원들에게 공유하는 작업도 하지 못했다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 몇 가지 개선 방법을 알게 되었다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Claude Pro 요금제에서는 Sonnet을 쓰는 편이 낫다. Opus의 사용량을 감당하기 어렵다.&lt;&#x2F;li&gt;
&lt;li&gt;Agent Team은 토큰을 많이 사용하므로 지양하고, Skill이나 SubAgent를 사용하는 편이 낫다. 모든 팀원이 Claude를 쓰는 것은 아니므로 범용성 면에서도 더 좋다.&lt;&#x2F;li&gt;
&lt;li&gt;특정 작업은 Codex에 위임하여 토큰을 아낄 수 있다. 며칠 전 OpenAI에서 공식적으로 Claude Code에서 Codex를 호출하는 플러그인을 출시했다.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;03-29-idongseog-kocinim-iyagi&quot;&gt;03&#x2F;29 이동석 코치님 이야기&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;개발자는 가까운 불편함을 해결하는 사람&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;개발자를 거창한 무언가를 만드는 사람으로만 생각하지 말고, 지금 반복해서 겪는 불편함을 개선하려는 태도를 먼저 가져야 한다는 이야기였다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;도구를 잘 다루는 것도 개발 실력의 일부&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;IDE, 에디터, 셸을 더 잘 다루는 것만으로도 생산성이 크게 달라진다. &quot;왜 이 불편함을 계속 참고 있지?&quot;를 자주 점검해야겠다고 느꼈다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;크래프트맨십: 내 이름을 걸 수 있는 코드를 작성하는가&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;결국 코드에 내 이름을 붙였을 때 설명하고 책임질 수 있는가의 문제라고 느꼈다. 부족하더라도 숨기지 말고 드러내고 피드백받는 태도가 중요하다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;03-31-gimhyeonsu-kocinim-keopicaes&quot;&gt;03&#x2F;31 김현수 코치님 커피챗&lt;&#x2F;h3&gt;
&lt;p&gt;팀원들과의 협업 방식에 대해 방향을 더 분명하게 잡을 수 있었던 대화였다. 후기는 &lt;em&gt;코어타임 &#x2F; 협업 회고&lt;&#x2F;em&gt;에서 정리하였다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;잘 아는 사람이 팀에서 설명하거나 자료를 공유해도 되는가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;설명 자체는 괜찮다. 오히려 설명은 내가 진짜 이해하고 있는지 검증하는 데 도움이 된다.&lt;&#x2F;li&gt;
&lt;li&gt;다만 잘 모르는 상태에서 아는 척 설명하면 잘못된 지식을 전달할 수 있으니, 모르면 모른다고 말하고 같이 찾는 태도가 중요하다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;링크나 자료 같은 문서를 공유하는 것도 괜찮은가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;공유와 강요는 다르다. 링크나 자료를 주는 것은 상대가 선택할 수 있으므로 괜찮다.&lt;&#x2F;li&gt;
&lt;li&gt;하지만 정리된 문서나 PRD와 같은 플랜을 줄 때는 왜 이렇게 정리했는지 설명할 수 있어야 한다.&lt;&#x2F;li&gt;
&lt;li&gt;단순히 GPT가 만든 결과물을 전달하는 것은 큰 의미가 없고, 내가 이해한 맥락까지 설명해야 가치가 생긴다.&lt;&#x2F;li&gt;
&lt;li&gt;이러한 공유가 목적이라면 공유도 괜찮고, 설명하는 것도 좋다. 단, 내가 하는 게 강요가 아닌지는 주의해야 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;체감하기에 성장 속도가 느린 것 같은데, 이런 고민을 다른 사람들은 어떻게 풀어내는가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;정글은 무언가를 완성하는 곳이라기보다, 나에게 맞는 학습 방식과 시작 전략을 찾아가는 과정에 가깝다.&lt;&#x2F;li&gt;
&lt;li&gt;제한된 시간 안에 모든 내용을 완벽하게 익히기는 어렵다. 학습 방식에는 정답이 없다. 넓게 훑는 사람도 있고 하나를 깊게 파는 사람도 있다.&lt;&#x2F;li&gt;
&lt;li&gt;개발자는 계속 학습해야 하는 사람이므로, 정글에서 본인에게 맞는 학습 방식을 찾아내었다면 그것만으로도 큰 가치가 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;04-04-dance-titaim&quot;&gt;04&#x2F;04 단체 티타임&lt;&#x2F;h3&gt;
&lt;p&gt;내 질문은 아니고, 다른 사람들의 질문을 정리하였다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;바이브 코딩이 너무 재미있어서 학습 코스의 내용에 집중하지 못했다. 어떻게 하는 게 좋을까?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;기본적으로는 정글 안에서는 바깥에서 배우기 어려운 CS나 소프트 스킬을 기르는 데 더 집중하는 것이 좋다.&lt;&#x2F;li&gt;
&lt;li&gt;바이브 코딩은 정글 밖에서도 혼자 충분히 할 수 있으므로, 현재 코스에 지장이 갈 정도로 비중을 두는 것은 권장하지 않는다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;수요코딩회의 바이브 코딩 결과물이 내부 구현 이해 없이 불완전한 결과물처럼 느껴진다. 이력서에 쓸 만한 가치가 있는가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;바이브 코딩으로 만들었다는 사실 자체가 문제라기보다, 그 사실을 전제로 무엇을 의도했고 어떤 식으로 AI를 활용했는지 설명할 수 있는지가 더 중요하다.&lt;&#x2F;li&gt;
&lt;li&gt;회사에서도 AI를 쓰고 있는 만큼, 해당 질문은 구체적인 구현 레벨이 아닌 &quot;개념은 이해했는가&quot;, &quot;검증과 테스트는 어떻게 했는가&quot;, &quot;다른 사람이나 에이전트와 어떻게 협업했는가&quot; 같은 부분을 물어볼 것이라 예상한다.&lt;&#x2F;li&gt;
&lt;li&gt;따라서 수요코딩회 결과물은 포트폴리오 프로젝트가 아닌, 이력서에 경험 한 줄과 대화 포인트를 만드는 정도를 목표로 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;suyokodinghoe&quot;&gt;수요코딩회&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chaekang&#x2F;Jungle_React_W5&quot;&gt;미니 React 구현 저장소&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;이번 주 수요코딩회에서는 미니 React를 구현했다.&lt;&#x2F;p&gt;
&lt;p&gt;React가 어떤 방식으로 동작하는지, 컴포넌트와 훅이 어떤 역할을 하는지 가볍게 구조를 파악할 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;협업 측면에서도 소통 빈도 자체는 높지 않았지만, 초반에 목표를 같이 맞춰 두니 비교적 안정적으로 구현이 진행되었다.&lt;&#x2F;p&gt;
&lt;p&gt;발표에서도 전반적으로 좋은 평가를 받았다. 다른 팀들에는 여러 지적이 있었던 것을 보면, 발표와 구현 모두 큰 문제 없이 마무리된 편이라고 생각한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;suyokodinghoe-hugi&quot;&gt;수요코딩회 후기&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;jaldoen-jeom-yujihal-jeom&quot;&gt;잘된 점 &#x2F; 유지할 점&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;싱크 맞추기&lt;&#x2F;strong&gt;: 초반에 함께 모여 목표와 구현 방향을 충분히 맞춰둔 덕분에, 중간에 한 차례 어긋난 시점을 제외하면 작업이 비교적 원활하게 진행되었다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;나눠서 개발하지 않기&lt;&#x2F;strong&gt;: 구현을 하나의 에이전트에서 한 것도 좋았다. AI를 적극적으로 활용하는 상황에서는 작업을 나누고, 각자 팀원이 별도의 에이전트로 개발한 뒤 AI로 머지 충돌을 해소하는 방식이 오히려 시간만 더 들고 의미없는 활동이라고 생각한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;aswiun-jeom-gaeseonhal-jeom&quot;&gt;아쉬운 점 &#x2F; 개선할 점&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;고민: AI를 사용하는 건가? AI에 의존하는 건가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;AI를 사용하니 다른 팀과 동일한 결과가 나온다. 이름이나 구현 디테일이 조금 달라도 전체 방향은 비슷한 경우가 대부분이다.
&lt;ul&gt;
&lt;li&gt;심지어 다른 팀이었는데도, 구체적인 로직의 특정 함수를 물어보면 서로 이야기가 가능할 정도였다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;우리가 요구사항을 정의하고 개발하고 있다기보다 모델의 학습 내용과 성능에 기대고 있는 것 아닌가 하는 의문이 든다.&lt;&#x2F;li&gt;
&lt;li&gt;이 문제를 줄이려면 과제 요구사항을 그대로 넣기보다, 팀이 정리한 해석과 설계 문서를 더 구체적으로 반영하는 방식이 필요할 수도 있겠다고 생각했다.&lt;&#x2F;li&gt;
&lt;li&gt;이런 고민이 있고, 답을 찾은 것은 아니지만 계속 고민해 볼 지점인 듯하다.
그럼 중간 설명을 줄이고, 원문 어투 유지해서 이렇게 가면 된다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;개선: 발표를 단순 기록보다 공유 중심으로 바꾸기 &amp;amp; 다양한 도전을 해보기.&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;(팀원인 송영진 님의 의견이었는데, 생각할 부분이 많아서 내 생각을 덧붙여 기록해 보았다.)&lt;&#x2F;li&gt;
&lt;li&gt;지금 발표는 &quot;무엇을 만들었고 어떻게 구현했다&quot;를 정리하는 데 그치고 있다. 그러다 보니 발표가 전반적으로 비슷해지고, 시행착오나 선택의 이유, 실패한 시도에서 얻은 점처럼 다른 사람에게 실제로 도움이 될 만한 내용은 잘 드러나지 않는다.&lt;&#x2F;li&gt;
&lt;li&gt;결국 발표가 동료학습에 도움이 되려면, 어떤 고민을 했고 무엇을 시도했으며 왜 그렇게 판단했는지를 공유해야 한다.&lt;&#x2F;li&gt;
&lt;li&gt;모두가 요구사항 구현에만 집중하거나, 새로운 시도가 있더라도 발표에서 잘 드러나지 않으면 결과는 쉽게 비슷해진다.&lt;&#x2F;li&gt;
&lt;li&gt;동료학습의 핵심은 서로 다른 시도와 그 과정에서 얻은 경험을 공유하는 데 있으므로, 다음에는 일부러 다른 방식으로 접근해 보거나 작은 실패를 감수하더라도 새로운 시도를 해 보고, 이를 발표 시간에 함께 공유해보는 게 좋을 것 같다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;개선: 데모는 요구사항과 동작 방식을 이해시키기만 하면 된다.&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;과하게 꾸미거나 실제 서비스처럼 보이게 만드는 것보다, 동작 원리가 잘 드러나는 구성이 중요하다.&lt;&#x2F;li&gt;
&lt;li&gt;이동석 코치님의 피드백 중에는, 이번 주차처럼 라이브러리를 만드는 과제의 경우 특정 기능만 간단히 보여주는 제한적인 데모와 해당 코드만 제시했어도 충분했을 것이라는 의견도 있었다. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ko.react.dev&#x2F;learn&quot;&gt;리액트의 튜토리얼 문서&lt;&#x2F;a&gt;처럼)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;koeotaim-hyeobeob-hoego&quot;&gt;코어타임 &#x2F; 협업 회고&lt;&#x2F;h3&gt;
&lt;p&gt;이번 주 알고리즘에서는 협업이 아주 잘 이루어졌다고 보기는 어려웠다.&lt;&#x2F;p&gt;
&lt;p&gt;나 역시 문제를 충분히 이해하지 못한 상태가 많아서 설명하거나 공유할 만한 지점을 만들기 어려웠고, 팀원들도 비슷한 상황이었다.&lt;&#x2F;p&gt;
&lt;p&gt;그리고 무언가 설명하면서 학습하는 성향의 팀원이 없었고, 그래서 자연스럽게 이야기나 공유가 많이 일어나지는 않은 듯하다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;haegsim-yeogryang-mogpyo-hoego&quot;&gt;핵심 역량 목표 회고&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;jal-doen-jeom&quot;&gt;잘 된 점&lt;&#x2F;h4&gt;
&lt;p&gt;두 목표 모두 완전히 달성하지는 못했고, 아쉬운 부분이 많다. 그럼에도 활동 기록을 통해 알고리즘 풀이 방식의 단점과 해결 방향을 잡았다는 것에서 의미가 있지 않을까 싶다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gomin-haegsim-yeogryang-mogpyoreul-eoddeohge-seoljeonghalgga&quot;&gt;고민: 핵심 역량 목표를 어떻게 설정할까?&lt;&#x2F;h4&gt;
&lt;p&gt;협업 목표나 주차 목표는 문제나 팀 상황에 따라 변수가 너무 많아서, 시작 전에 적어 둔 목표를 그대로 평가하는 방식이 항상 적절한지는 잘 모르겠다.&lt;&#x2F;p&gt;
&lt;p&gt;특히 이번 주처럼 난이도를 잘못 가늠했거나, 목표 자체의 방향이 어긋난 경우에는 달성 여부만으로 평가하기 어렵다고 느끼고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;협업 관련 목표는 계속 넣고 싶지만, 팀 성향과 학습 단계에 따라 적절한 목표가 달라져서 설정이 쉽지 않다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gomin-jaryo-gongyuwa-seolmyeong-eoddeon-bangsigi-jeogjeolhalgga&quot;&gt;고민: 자료 공유와 설명, 어떤 방식이 적절할까?&lt;&#x2F;h4&gt;
&lt;p&gt;이동석 코치님과의 커피챗 이후에는 자료 공유 자체를 조심해야 한다고 생각했는데, 김현수 코치님과의 커피챗을 거치면서 기준이 더 분명해졌다.&lt;&#x2F;p&gt;
&lt;p&gt;두 코치님의 공통된 의견은, 자료 공유나 설명 자체가 문제가 아니라 그것이 강요처럼 느껴지거나 팀의 사고를 대신하는 방식이 되면 안 된다는 것이었다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 이동석 코치님은 잘 아는 사람이 먼저 방향을 정해 주거나 자료를 많이 제공하는 것 자체를 경계하는 편이었고, 김현수 코치님은 강요만 아니라면 자신이 이해한 맥락까지 함께 설명하는 공유는 충분히 의미 있다고 보는 편이었다.&lt;&#x2F;p&gt;
&lt;p&gt;나는 두 의견을 고려하여, 팀원이 취사선택할 수 있고 강요처럼 보이지 않으며 공유의 이유를 납득 가능하게 전달할 수 있다면 의미 있는 행동이라고 정리했다.
지금까지의 경험 상 도움이 되었다는 의견을 많이 받았기 때문이다. &lt;del&gt;해보고 별로면 바꾸면 된다.&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;p&gt;내 경험을 예시로 들어보면, Week3 Redis 주차에서 핵심 키워드와 질문 목록을 정리해 각자 조사해오게 했는데, 이는 강제는 아니었지만 숙제처럼 느껴질 여지가 있었다.&lt;br &#x2F;&gt;
반면 Week4에서 React 학습 자료를 공유한 방식은 각자 선택적으로 참고하거나 다른 자료를 찾아보는 흐름으로 이어져 부담이 적었다.&lt;&#x2F;p&gt;
&lt;p&gt;앞으로는 답이나 방향을 먼저 제시하기보다, 필요할 때 가볍게 참고할 수 있는 자료를 공유하거나 내가 이해한 내용을 설명하는 방식을 기본으로 하려 한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daeum-jucae-sidohal-geos&quot;&gt;다음 주차에 시도할 것&lt;&#x2F;h4&gt;
&lt;p&gt;다음 주부터는 C 언어와 관련된 파트에 들어가므로, 개인적으로 더 기대하던 내용을 학습하게 된다. 그만큼 이번 주보다 더 적극적으로 참여하고, 개인 학습 목표도 조금 더 구체적으로 세워 볼 생각이다.&lt;&#x2F;p&gt;
&lt;p&gt;협업 쪽에서는 자료 공유를 다시 도입하되, 회고에서 말한 것처럼 강요가 아닌 선에서 가볍게 공유하려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;AI 활용도 보조 목표로 두고, 코스의 학습과 협업을 방해하지 않는 선에서 꾸준히 할 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;이외의 구체적인 계획은 팀원들의 성향과 코스의 상황에 따라 달라질 수 있으므로, 고정된 방식보다는 상황에 맞게 조정하는 편이 더 적절할 것 같다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 2026년 3월</title>
          <pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-2026-03/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-2026-03/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-2026-03/">&lt;p&gt;이번 달 초부터 정글 활동을 시작해 하루 종일 커리큘럼에 집중하고, 여유 시간에는 AI 활용 연습을 겸해 토이 프로젝트를 진행하고 있다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;tobiyi-seupeuring-claude-codereul-iyonghae-seupeuring-aeb-gaebalhagi-1hoeca-2hoeca&quot;&gt;토비의 스프링 — Claude Code를 이용해 스프링 앱 개발하기: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;live&#x2F;gdg4DBcakIg?si=-5n5Qq_EDlk5Lbw_&quot;&gt;1회차&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;live&#x2F;ECK6jZWixtk?si=zorjjplWRVpwvye3&quot;&gt;2회차&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;토비(이일민)가 AI 에이전트를 활용해 개발을 진행하는 라이브 영상.&lt;&#x2F;p&gt;
&lt;p&gt;시니어 개발자가 실제로 어떤 방식으로 작업하는지 확인할 수 있으며, 서브 에이전트 구성이나 팀 단위 활용 방식, AI를 개선하는 방법 등을 이해하는 데 도움이 된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;danil-peuroseseu-peurogeuraeming-noteu-go-sqlite-beonyeog&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crawshaw.io&#x2F;blog&#x2F;one-process-programming-notes&quot;&gt;단일 프로세스 프로그래밍 노트 — Go + SQLite&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wjkoh.com&#x2F;posts&#x2F;one-process-programming-notes&#x2F;&quot;&gt;번역&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;나도 이런 철학을 좋아하긴 함. 모든 사람이 하루 다운타임 몇 분도 못 버틸 만큼 중요한 서비스를 하고 있는 건가? (물론 버그 대응이나 그런 상황이라면 무중단이 좋기야 하겠지만..?)&lt;&#x2F;p&gt;
&lt;p&gt;가능한 가장 단순한 스택을 쓰는 게 좋지 않나 싶다. 특히 AI를 많이 쓰거나 자동화된 테스트가 필요한 경우에는 단순한 구성의 강점이 더 드러날 것이라 생각한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;claude-codereul-mandeulmyeo-baeun-geos-uriga-skillsreul-sayonghaneun-bangbeob-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;trq212&#x2F;status&#x2F;2033949937936085378?s=12&amp;amp;t=1bi3eg1xL3Pa2E0i0jg18g&quot;&gt;Claude Code를 만들며 배운 것: 우리가 Skills를 사용하는 방법&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27640&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;요즘 스킬을 많이 쓰고 있어서 메모. Anthropic 내부에서 수백 개의 스킬을 운용하며 축적한 노하우 공개.&lt;&#x2F;p&gt;
&lt;p&gt;스킬 구현 시 참고하고 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;openaiyi-claude-codeyong-codex-peulreogeuin-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openai&#x2F;codex-plugin-cc&quot;&gt;OpenAI의 Claude Code용 Codex 플러그인&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=28023&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Claude Code 환경에서 OpenAI Codex를 직접 호출해 사용할 수 있는 공식 플러그인이 OpenAI에서 출시됨.&lt;&#x2F;p&gt;
&lt;p&gt;최근 Claude Pro만으로는 토큰이 부족한 경우가 많아
정글에서 제공된 OpenAI Pro 모델을 활용하기 위해 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;skills-directory&#x2F;skill-codex&quot;&gt;&lt;code&gt;skill-codex&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; 같은 플러그인을 통해 Codex 에이전트에 작업을 위임하는 방식을 고려하고 있었는데,
이 기능을 타이밍 좋게 OpenAI가 공식적으로 지원하게 되었다.&lt;&#x2F;p&gt;
&lt;p&gt;직접 사용해보고, 다음 월간 기록에 후기를 정리할 예정이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cpython-3-15yi-jit-dasi-gwedoe-oreuda-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.python.org&#x2F;2026&#x2F;03&#x2F;jit-on-track&#x2F;&quot;&gt;CPython 3.15의 JIT, 다시 궤도에 오르다&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27971&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;CPython이 JIT를 도입하려고 하고 있었는데, 최근 3.15부터 성과가 나오기 시작한 듯하다.&lt;&#x2F;p&gt;
&lt;p&gt;CPython이 JIT까지 시도하고 있는 줄은 몰랐는데 알게 되었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-sidaeedo-peurogeuraemingeul-baeweoya-haneunga-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;htmx.org&#x2F;essays&#x2F;yes-and&#x2F;&quot;&gt;AI 시대에도 프로그래밍을 배워야 하는가&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27550&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;그렇다. 복잡성을 다루는 능력은 언제나 중요하다. 하지만, 코딩 실력이 덜 중요해질 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;Montana State University 컴퓨터공학과 교수이자 htmx 창시자인 Carson Gross의 에세이.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2026nyeon-google-geomsaegeun-wanjeonhi-manggajyeossda-nae-opeunsoseuyi-seo-jeonjaengeseo-jigo-isseum-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;Gavriel_Cohen&#x2F;status&#x2F;2028821432759717930&quot;&gt;2026년, Google 검색은 완전히 망가졌다 - 내 오픈소스의 SEO 전쟁에서 지고 있음&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27184&quot;&gt;GeekNews&lt;&#x2F;a&gt;)&lt;&#x2F;h3&gt;
&lt;p&gt;NanoClaw 오픈소스 프로젝트 사칭 사이트가 구글의 검색 상위에 노출되는 문제를 호소하는 글.&lt;&#x2F;p&gt;
&lt;p&gt;처음엔 관리자 본인의 책임 아닌가 싶었는데, 선의의 개발자가 구글의 SEO 문제로 인해 불필요한 문의와 시간 피해를 받는 상황이 억울할 수 있겠다는 생각이 든다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;haneseu-enjinieoringiran-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wikidocs.net&#x2F;blog&#x2F;@jaehong&#x2F;9481&#x2F;&quot;&gt;하네스 엔지니어링이란?&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27667&quot;&gt;GeekNews&lt;&#x2F;a&gt;)&lt;&#x2F;h3&gt;
&lt;p&gt;글이 되게 짧고 빈약하지만 처음 개념을 이해하기에는 좋아 보임.&lt;&#x2F;p&gt;
&lt;p&gt;하네스는 AI가 이상하게 돌지 않게 감싸는 도구&#x2F;프롬프팅을 의미, 원래부터 있던 건데 도구가 다양해지고 생태계가 커지니까 용어가 붙은 거라고 생각한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;portless-poteu-beonhoreul-ireum-giban-localhost-urlro-daecehaneun-dogu-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vercel-labs&#x2F;portless&quot;&gt;portless - 포트 번호를 이름 기반 .localhost URL로 대체하는 도구&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27116&quot;&gt;GeekNews&lt;&#x2F;a&gt;)&lt;&#x2F;h3&gt;
&lt;p&gt;Vercel Labs의 오픈소스 도구. 로컬 개발 시 포트 충돌을 이름 기반 &lt;code&gt;.localhost&lt;&#x2F;code&gt; URL로 해결해 준다.&lt;&#x2F;p&gt;
&lt;p&gt;자동 포트 할당(4000~4999 범위)과 git worktree 연동을 지원한다고 한다. 특히 worktree 지원이 유용해 보이는데, 지금은 브라우저 주소가 필요한 개발을 잘 안 하지만 나중에 필요해지면 써볼 계획이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;geu-oe-sujibhan-geul&quot;&gt;그 외 수집한 글&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47323017&quot;&gt;&lt;strong&gt;잇따른 장애 후, Amazon이 AI 지원 코드 변경에 시니어 엔지니어 승인 의무화&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27395&quot;&gt;GeekNews&lt;&#x2F;a&gt;): AI 코딩 도구로 인한 연이은 서비스 장애 이후, 주니어&#x2F;미드레벨 엔지니어의 AI 지원 코드 변경에 시니어 승인을 의무화했다는 소식.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47357042&quot;&gt;&lt;strong&gt;&quot;구현할까요? 아니요 (feat. claude-opus-4-6)&quot;&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27451&quot;&gt;GeekNews&lt;&#x2F;a&gt;): Claude가 구현 여부를 물었는데 사용자가 &quot;아니요&quot;라고 답하자, &quot;묻지 말고 그냥 해라&quot;로 재해석한 사례. AI는 이런 점에서 아직 완전하지 않다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47423647&quot;&gt;&lt;strong&gt;Rob Pike의 프로그래밍 5가지 규칙 (1989)&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27631&quot;&gt;GeekNews&lt;&#x2F;a&gt;: 그중 제일 핵심인 1번 룰, &quot;병목임이 입증되기 전까지 속도 개선 시도 금지&quot;가 매번 볼 때마다 인상 깊음.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;devday.kr&#x2F;article&#x2F;tony-hoare-passed-away-turing-award-winner&quot;&gt;&lt;strong&gt;퀵소트의 아버지, 토니 호어 별세&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; 퀵소트를 배우는 중에 접한 소식. CS 분야가 활발해진 지 50~70년밖에 안 됐다는 걸 실감하게 된다. 전설적인 인물들이 살아 있다는 게 다른 분야에선 쉽지 않은데. (그나저나 저 글은 연도나 설명이 잘못된 게 많아 보임.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47339164&quot;&gt;&lt;strong&gt;AI 면접 봇 인터뷰&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (Hacker News): The Verge의 AI 채용 봇 인터뷰 영상보다 HN 코멘트들에 여러 의견이 많아서 더 인상 깊음. 사람을 상대하는 영역에서 AI를 쓰면 원가 절감이나 노력을 덜 들이려는 의도로 느껴지는 면이 없잖아 있는 듯하다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;modernaicourse.org&#x2F;&quot;&gt;&lt;strong&gt;CMU 10-202: 현대 인공지능 입문&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=27144&quot;&gt;GeekNews&lt;&#x2F;a&gt;): 카네기멜론대학 강의. 스탠포드 CS146S는 실제 사용 위주였는데, 이건 공부 위주인 듯. AI는 많이 바뀌지만 핵심은 잘 안 바뀌는 느낌. AI를 배우려면 이런 게 더 오래가는 지식일지도?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gameworkerkim&#x2F;coruna_analysis&#x2F;blob&#x2F;main&#x2F;ANALYSIS_KR.md&quot;&gt;&lt;strong&gt;Coruna 멀웨어 분석&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: 2024년에 미국에서 관리되던 공격 도구가 유출된 사건. 국가 기밀로 관리되는 이런 취약점이 많을 수도 있다는 점이 꽤나 걱정스럽긴 함.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;fakedev9999&#x2F;status&#x2F;2025941293155959198?s=20&quot;&gt;&lt;strong&gt;Why I&#x27;m Mass-Deleting My Rust Code - X.com&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: AI 출력을 검증할 수 있는 하네스(테스트, CI&#x2F;CD, 모니터링)를 갖추면, 더 빠른 언어, 도구 등을 사용하는 게 효율적이라는 주장.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;jjalbeun-geul-jehan-eobsneun-ai-gaebaleun-wiheomhada&quot;&gt;짧은 글: 제한 없는 AI 개발은 위험하다.&lt;&#x2F;h3&gt;
&lt;p&gt;아직, 그리고 앞으로도 제한 없는 AI 개발은 위험할 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;Amazon에선 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47323017&quot;&gt;&lt;strong&gt;AI 기반 결과물에 시니어 승인을 필수로 요구하기 시작했다.&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; 또한, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47357042&quot;&gt;사용자의 거절을 무시하고 코드를 실행한 경우도 있다.&lt;&#x2F;a&gt; 정글 교육실에서도 Codex 에이전트가 한 분의 D 드라이브를 통째로 날려버린 사례가 있었다.
인터넷에서나 보던 일을 실제로 목격하니, AI에게 모든 권한을 위임하는 것의 위험성을 체감할 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;개인적으로는 이런 문제가 발생하는 근본 원인은 AI가 단순한 토큰 생성기이며 여러 한계를 가지고 있기 때문이라고 생각한다.
컨텍스트의 제한이 있고, 인간과 비슷한 사고를 하는 듯 보이는 LLM의 특성상 생성은 잘 되더라도 적절한(기계, 그리고 인간이 이해 가능한) 추상화 레벨 없이 구현만 있다면 언젠가는 문제가 발생할 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;현실의 복잡한 문제를 다룰 수 있는 구조를 설계하고 관리하는 것이 개발자의 핵심 능력이었다고 생각하며, 도구가 바뀌었을 뿐 이 본질은 동일하다고 본다.
최근 정글 수요코딩회에서 바이브 코딩 방식으로 해 보면서, 개발 지식 없이는 잘 안 된다는 걸 다들 체감한 분위기였다.&lt;&#x2F;p&gt;
&lt;p&gt;따라서 결국 (인간과 기계가 이해 가능한) 코드의 관리가 더 중요해지며, 사람의 관리가 필요할 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;생각해 보면 RAG, MCP, 에이전트, Skill 등 여러 발전 과정 역시 이러한 문제를 해결하기 위해 나왔다고 생각하는데, 최근에는 AI가 의도한 결과물을 낼 수 있도록 도구와 환경을 구성하는 것을 하네스(harness)라고 모아 부르는 듯하다.&lt;&#x2F;p&gt;
&lt;p&gt;물론 언젠가는 사람의 개입 없이도 가능한 방식이 있겠지만... 그게 되면 내가 개발자로 있을 것 같지는 않다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gaein-toipeurojegteu-jungle-bell&quot;&gt;개인 토이프로젝트 - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-bell&quot;&gt;Jungle Bell&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;크래프톤 정글 출석체크 알림용 시스템 트레이 앱.&lt;&#x2F;li&gt;
&lt;li&gt;AI를 적극적으로 써서 배포하고 실사용자까지 나온 첫 프로젝트.&lt;&#x2F;li&gt;
&lt;li&gt;여러 AI기능을 연습할 수 있는 플레이그라운드로 활용할 예정이다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;jungle-sw-ai-lab-hwaldong&quot;&gt;Jungle SW-AI Lab 활동&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;1juca-minipeurojegteu&quot;&gt;1주차 미니프로젝트&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;jungle&#x2F;jungle-essay&#x2F;&quot;&gt;정글 에세이: 퇴사하고 정글에 온 이유&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;: 팀 미니프로젝트 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-mini-project&quot;&gt;JungleQA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;2juca-algorijeum&quot;&gt;2주차 알고리즘&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;jungle&#x2F;jungle-week02&#x2F;&quot;&gt;Week 02: 컴퓨팅 사고로의 전환&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;: 수요코딩회 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;surfing-go&quot;&gt;Surfing Go&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;3juca-algorijeum&quot;&gt;3주차 알고리즘&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;jungle&#x2F;jungle-week03&#x2F;&quot;&gt;Week 03: 컴퓨팅 사고로의 전환&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;jungle&#x2F;jungle-cs&#x2F;&quot;&gt;CS 공부 내용 정리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;: 수요코딩회 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;minimi&quot;&gt;Minimi&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;4juca-algorijeum&quot;&gt;4주차 알고리즘&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;글&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;jungle&#x2F;jungle-week04&#x2F;&quot;&gt;Week 04: 컴퓨팅 사고로의 전환&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트&lt;&#x2F;strong&gt;: 수요코딩회 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;dom-vdom&quot;&gt;dom-vdom&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tobiyi-seupeuring-raibeu-jeongri-claude-codereul-iyonghan-spring-aeb-gaebal-gaideu&quot;&gt;토비의 스프링 라이브 정리: Claude Code를 이용한 Spring 앱 개발 가이드&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;eb8c640010f968d2e7c6a86036243939&quot;&gt;토비(이일민)의 라이브 세션을 보고 정리한 글.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;회사에서도 AI의 결과를 직접 다듬으면서 시간을 썼는데, 시니어조차 AI를 제한하려 하지 않고 직접 코드를 쓰지 않는 방식으로 작업하는 모습을 보면서, 그리고 그것이 높은 효율을 내는 걸 보면서 이런 식으로도 AI를 활용할 수 있다는 점을 알게 된 게 큰 도움이 되었다. 지속적으로 참고하면서 따라 해 보려고 한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;claude-tmux-sayongbeob-baeugi&quot;&gt;Claude &amp;amp; Tmux 사용법 배우기&lt;&#x2F;h3&gt;
&lt;p&gt;최근 토비의 라이브 영상을 보면서, 내가 AI를 사용하기만 했지 잘 써볼 생각은 안 했다고 느끼며, AI를 효율적으로 쓰는 여러 기술을 찾아보고 시도해 보고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;Agent Team 같은 병렬 작업 환경에서는 Tmux가 꽤 유용해 보여서 사용하기 시작했다. 아직은 익숙하지 않지만, 최대한 적응해 보려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;현재는 Ghostty + Tmux 조합을 사용 중이다. cmux도 괜찮아 보여서 설치해 봤지만, 기능이 너무 많아 일단은 사용하지 않기로 했다. 알림이나 인터랙션 측면에서는 좋아 보이는데, 분할 환경에 익숙하지 않아서 어려웠다.
게다가 Claude와 GPT 모두 프로 요금제를 쓰고 있어서, 병렬 에이전트를 쓰면 토큰이 먼저 바닥나서 cmux의 장점을 쓰기에도 좀 어려웠다.&lt;&#x2F;p&gt;
&lt;p&gt;그래서 tmux에 익숙해지고, 여러 병렬 처리가 필요해진다면 cmux를 다시 시도해보지 않을까 싶다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hyeonjae-wicieseo-ghostty-silhaenghaneun-keoseuteom-gineung-doib&quot;&gt;현재 위치에서 Ghostty 실행하는 커스텀 기능 도입&lt;&#x2F;h3&gt;
&lt;p&gt;tmux를 쓰기 시작하면서, 원래 사용하던 IDE 내장 터미널보다 Ghostty를 더 자주 쓰게 됐다.&lt;br &#x2F;&gt;
그런데 VS Code나 JetBrains IDE처럼 현재 프로젝트 위치에서 바로 프로그램을 여는 기능이 없어서, 매번 앱을 실행한 뒤 &lt;code&gt;cd&lt;&#x2F;code&gt;로 원하는 경로로 이동해야 했다.&lt;&#x2F;p&gt;
&lt;p&gt;그래서 &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt;에 현재 작업 디렉터리에서 Ghostty를 바로 열 수 있는 함수를 추가했다.&lt;&#x2F;p&gt;
&lt;p&gt;원래는 이런 식의 커스텀 설정을 그다지 선호하지 않는다. 기본 설정에 익숙해지는 편이 더 범용적이고 낫다고 생각하기 때문이다.
다만 지금처럼 기본 설정이 없거나 작업 효율에 체감 차이가 큰 경우라면, 이런 설정도 적절히 도입해 볼 만한 듯하다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jjalbeun-saenggag&quot;&gt;짧은 생각&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;근황과 요즘 하는 생각&lt;&#x2F;p&gt;
&lt;p&gt;크래프톤 정글에서 하루 대부분을 공부에 집중하고 있다.&lt;br &#x2F;&gt;
취업 이후에는 이 정도의 시간을 투자하기 어려운데다, 근본적으로 중요한 내용을 깊게 다룰 수 있고 같은 내용을 배우는 동료들이 있는 환경이기 때문에 최대한 집중하려고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;여유 시간이 생기면 AI 활용 역량을 높이기 위한 연습을 겸해 Jungle Bell을 개발하고 유지&#x2F;관리하고 있다.&lt;br &#x2F;&gt;
캠퍼스에서 외부 IP가 동일해 실제 최소 사용자는 16명 이상이지만, GitHub Release 다운로드 수는 1~2회만 집계되어 이를 어떻게 수치화할지 고민이다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Week 04: 컴퓨팅 사고로의 전환</title>
          <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week04/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week04/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week04/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-oebu-jaryo-eobsi-ijin-geomsaeg-teuri-dfs-bfs-wisangjeongryeol-guhyeonhagi&quot;&gt;목표 1. 외부 자료 없이 이진 검색 트리, DFS&#x2F;BFS, 위상정렬 구현하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 구현, 품질, 설계&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;이진 검색 트리, DFS&#x2F;BFS, 위상정렬 알고리즘을 외부 자료 없이 스스로 설명하고 구현해낼 수 있어야 한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;월요일까지 중 난이도 문제까지 완료하고, 이후 제한 시간을 두고 문제 풀이 또는 핵심 기능을 재구현하기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;계획했던 재구현 과정은 따로 진행하지 못했지만, 기본 문제를 풀면서 일부 문제를 AI나 힌트 없이 직접 구현하는 과정에서 자연스럽게 목표를 달성했다고 판단했다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;계획과 과정은 달랐지만 목표 자체는 달성.&lt;&#x2F;p&gt;
&lt;p&gt;외부 자료 없이 이진 검색 트리, DFS&#x2F;BFS, 위상정렬을 활용한 문제 풀이가 가능했다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-2-gibon-jegong-gangyi-oeyi-algorijeum-munjereul-pulgi&quot;&gt;목표 2. 기본 제공 강의 외의 알고리즘 문제를 풀기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: 문제해결, 학습 민첩성, AI 활용&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Week 4 문제 풀이 외의 문제도 중(실버 상급 ~ 골드) 난이도 정도로 4문제 이상 풀이 시도하기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-1&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;문제 배경: 3주차에는 시간 제한을 두고 문제를 풀며 풀이 속도는 향상되었지만, 개인 활동에 시간을 분산하면서 2주차와 풀이량이 거의 동일하게 유지되었다.&lt;&#x2F;p&gt;
&lt;p&gt;개선 계획: 정규 시간에는 커리큘럼 활동에 집중하고, 개인 활동은 정규 수업 외 시간과 식사 시간에만 진행한다.
또한, 문제별 소요 시간을 타이머로 기록하고, 템플릿을 활용해 AI 사용 방법, 풀이 전&#x2F;중&#x2F;후의 계획과 판단 근거를 정리한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;난이도는 실버 1~골드 5로, 목표 범위(실버 상급 ~ 골드) 내의 추가 문제 6개를 선정했고 그중 3문제를 풀었다.&lt;&#x2F;p&gt;
&lt;p&gt;3&#x2F;21(금)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;f4a4e77&quot;&gt;basic 문제 전체 풀이 완료&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;97a026a&quot;&gt;트리만들기&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;fdffcb6&quot;&gt;상근이의여행&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;3dbdd12&quot;&gt;바이러스&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;7689519&quot;&gt;점프왕쩰리&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;35acdbe&quot;&gt;트리의부모찾기&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;026b7a7&quot;&gt;연결요소의개수&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;3&#x2F;23(일) 난이도 중 문제 집중 풀이:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;78b75a5&quot;&gt;이진검색트리&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;e1cf3d8&quot;&gt;작업&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;179d080&quot;&gt;DFS와BFS&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;6a346e4&quot;&gt;미로탐색&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;7383fee&quot;&gt;이분그래프&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;43cb406&quot;&gt;동전2&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;3&#x2F;24(화) 추가 문제 진행:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;93882a5&quot;&gt;AtoB&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;7e6ff76&quot;&gt;쉬운최단거리&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commit&#x2F;7751342&quot;&gt;적록색약&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-1&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;난이도 중 이하 문제를 다 푼 후, 목표의 4문제 대비 3문제 완료.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-3-jaryo-gongyu&quot;&gt;목표 3. 자료 공유&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;small&gt;관련 역량: AI 활용, 협업&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;p&gt;내 경험&#x2F;지식을 활용해서 팀 학습에 기여하기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-2&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;이번 주차의 알고리즘을 잘 설명해주는 자료를 찾으면 공유하기.&lt;&#x2F;p&gt;
&lt;p&gt;팀원들의 진행 상태를 확인하고 알고리즘의 개념에 대해서 이야기하기. (같이 배우기)&lt;&#x2F;p&gt;
&lt;p&gt;수요코딩회의 미니 React 구현에 필요한 HTML&#x2F;CSS&#x2F;JS, DOM 조작, 브라우저 구성 요소, 렌더링 등의 개념 관련 자료를 정리해서 제공하기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-2&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;수요코딩회의에서 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;68e39f4fbb9b64b06e1df78bb8c3342a&quot;&gt;미니 React 구현을 위한 자료&lt;&#x2F;a&gt;를 정리해서 공유.&lt;&#x2F;p&gt;
&lt;p&gt;기존 알고리즘 템플릿&#x2F;예시 공유용 Gist가 관리하기 어려워, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;1bb63c2d9b8f21292cfd28ed746b578c&quot;&gt;새로운 학습&#x2F;공유용 Gist&lt;&#x2F;a&gt;로 새로 작성.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-2&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;팀원들과 알고리즘을 공유하는 것에 대해서는 잘 지켜지지 못한 듯함. 팀원 전체적으로 공감하는 부분이었음.&lt;&#x2F;p&gt;
&lt;p&gt;수요코딩회에서는 Codex Skill을 추가하자고 의견을 제시하거나, 이론 설명 등에서 적절하게 참여했다고 생각함.&lt;&#x2F;p&gt;
&lt;p&gt;단, 3&#x2F;24의 이동석 코치님과의 커피챗에서 자료를 미리 만들어 공유하는 것에 대해서는 좋지 않다는 피드백을 받았음. 자료 공유 관련해서는 회고 파트에서 설명.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;03-24-idongseog-kocinim-keopicaes&quot;&gt;03&#x2F;24 이동석 코치님 커피챗&lt;&#x2F;h3&gt;
&lt;p&gt;인상 깊은 질문과 답변 위주로 정리하였다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;수요코딩회의의 우선순위(이론&#x2F;AI&#x2F;협업&#x2F;제품 이해)&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;우선순위를 나누는 접근 자체가 잘못되었다. 기술 이해, AI 활용, 협업은 분리되지 않고 동시에 작동하는 구조이며, &quot;무엇을 구현할지 이해하면서 구현하는 과정&quot;이 중심이다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;수요코딩회의 바이브 코딩 걱정 (코드를 봐야 하는가? 사고까지 AI에게 맡기는 문제)&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;바이브 코딩 자체는 문제가 아니다. 구현 디테일보다 명세와 방향 관리 능력이 중요.&lt;&#x2F;li&gt;
&lt;li&gt;다만 what까지 AI가 결정하면 문제. 사람은 명세와 방향을 정의하고, AI는 how를 담당하는 구조가 맞다.&lt;&#x2F;li&gt;
&lt;li&gt;수요코딩회의의 본질도 기능 구현이 아니라, AI를 활용하면서 결과를 의도한 방향으로 통제하는 능력을 기르는 것.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;잘 아는 사람이 협업에서 자료 공유나 적극적으로 나서는 것이 좋을까?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;협업에서 잘하는 사람이 먼저 나서서 리딩하는 방식은 비추천. 잘하는 사람이 말하면 모두 따라가고, 의견 다양성과 학습 기회가 사라진다.&lt;&#x2F;li&gt;
&lt;li&gt;과도한 자료 공유도 부담&#x2F;숙제처럼 느껴질 수 있음.&lt;&#x2F;li&gt;
&lt;li&gt;먼저 결론을 제시하지 말고 질문을 던지고, 막힐 때만 개입하는 흐름 조정자 역할이 맞다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;개인의 실력 향상이 안 되는 것 같다는 고민 &#x2F; 팀원 간 차이에 대해서&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;여러 요인이 있겠지만, 여러 학생들을 본 경험상 본인의 멘탈이나 건강에 대한 부분을 체크해 보는 것도 필요할 수 있음.&lt;&#x2F;li&gt;
&lt;li&gt;성장 체감이 안 되는 문제에 대해서는, 비교 기준 자체를 재점검해야 한다. 성장의 범위는 기술 능력뿐 아니라 협업 능력, 사람을 성장시키는 능력까지 포함.
&lt;ul&gt;
&lt;li&gt;오히려 제일 쉬운 게 기술 공부이고 혼자서도 가능함. 반면에 함께 일하는 걸 배우는 건 쉽지 않고 기회도 적음. 오히려 협업 능력을 키울 수 있는 기회로 보아야 함.
&lt;ul&gt;
&lt;li&gt;팀 내 실력 편차가 클 때, 개인 성장보다 팀을 어떻게 움직이느냐가 중요. &quot;내가 얼마나 잘하냐&quot;가 아니라 &quot;팀을 어떻게 끌어올리냐&quot;가 올바른 기준.&lt;&#x2F;li&gt;
&lt;li&gt;도와주는 방식은 요청 기반, 상황 기반 개입이 원칙. &quot;얼마나 알려주느냐&quot;가 아니라 &quot;언제 어떻게 개입하느냐&quot;가 핵심.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;C나 PintOS같은 어려운 커리큘럼의 선행학습이 필요한가?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;C 선행학습은 불필요. 특정 언어보다 코딩 능력이 중요하며, 빈 종이에 코드를 직접 작성할 수 있는지가 기준. Python으로 코딩 반복이 최우선.&lt;&#x2F;li&gt;
&lt;li&gt;선행학습은 추천하지 않음. 오히려 지금 커리큘럼에 더 집중하는 걸 추천함.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;알고리즘의 경우, 하루 30분에서 1시간 정도의 시간을 투자해서 감각을 유지하는 건 도움이 될까?&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;알고리즘을 짧은 시간(30분 내외) 가볍게 반복해서 푸는 정도는 추천.&lt;&#x2F;li&gt;
&lt;li&gt;다만 커리큘럼 방해나 수면 감소를 초래할 정도의 과도한 투자는 피해야 한다. 오히려 이게 부채처럼 느껴져서 스트레스가 된다면 피해야 함.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;03-26-gimhyeonsu-kocinim-jeomsimsigsa&quot;&gt;03&#x2F;26 김현수 코치님 점심식사&lt;&#x2F;h3&gt;
&lt;p&gt;팀원이 3명이라 자리가 하나 비어서 그런지, 김현수 코치님이 합석해 주셔서 여러 이야기를 나눌 수 있었다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;수요코딩회의의 의도와 목적&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;지금 코스에서 배우는 자료구조와 연결되는 경험을 하게 하는 것이 목적.&lt;&#x2F;li&gt;
&lt;li&gt;&quot;자료구조 열심히 했습니다&quot;로 끝나는 것과, &quot;미니 React를 만들면서 DFS와 트리 기반 설계를 실제로 해봤다&quot;라고 말할 수 있는 것은 다르다.&lt;&#x2F;li&gt;
&lt;li&gt;특정 기술(예: 레디스, 리액트) 자체가 중요한 게 아니라, 배우고 있는 자료구조(트리, DFS&#x2F;BFS)를 실제 존재하는 문제에 적용해보는 것이 핵심.&lt;&#x2F;li&gt;
&lt;li&gt;이런 경험은 면접이나 대화에서 했던 일을 구체적으로, 오래 이야기할 수 있는 활동의 증명이 된다. 책이나 이론을 외운 것과 달리 자세하게 답하기 쉽고, 듣는 사람도 &quot;열심히 했구나&quot;라고 느끼기 쉽다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;실제로 면접관이 GitHub을 보는지 질문 &#x2F; README 관리의 필요성&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;공고를 열면 아주 많은 지원서를 본다. 1차 필터링에서 이력서만으로 애매한 경우에 추가 자료(README, GitHub, 블로그, 유튜브 등)가 관리되어 있는지에 따라 탈락 여부나 추가 검토 대상이 결정될 수 있다.&lt;&#x2F;li&gt;
&lt;li&gt;README는 모르는 사람도 보기 좋게 키워드 중심으로 정리해야 한다. 지금 당장 완성할 필요는 없지만, 나중에 다시 쓸 때 기억할 수 있도록 어필 포인트나 키워드 정도는 매 주차마다 기록해 두는 게 좋다.&lt;&#x2F;li&gt;
&lt;li&gt;AI 활용 같은 스킬도 좋은 포인트가 될 수 있고, 추가한 기능들에 대한 정보도 레포 안에 남겨둬서 실제로 그렇게 했다는 걸 확인할 수 있게 해야 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;algorijeum-jaryogujo-jeongri&quot;&gt;알고리즘&#x2F;자료구조 정리&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;1bb63c2d9b8f21292cfd28ed746b578c&quot;&gt;코딩 테스트를 위한 파이썬 문법과 알고리즘 정리&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;suyokodinghoe-hugi&quot;&gt;수요코딩회 후기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;잘 된 점 &#x2F; 유지할 점:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;첫 회의에서 목표를 확실하게 설정했음. 우리가 뭘 모르는지, 어떤 걸 만들어야 하는지를 먼저 정리하고 시작하니 방향이 흔들리지 않았음.&lt;&#x2F;li&gt;
&lt;li&gt;1시간 간격으로 공부&#x2F;작업 현황을 공유하거나 모르는 내용을 이야기하는 등 팀원 간의 싱크를 맞추는 시간을 가졌음.&lt;&#x2F;li&gt;
&lt;li&gt;AI 활용을 적극적으로 시도했음. 이번에는 Skill.md를 만들어서 반복 작업을 개선했고, 앞으로는 에이전트나 프롬프트 규칙 등을 지속적으로 피드백하면서 개선해보는 것도 좋을 듯.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;고민: 꼭 코드를 나눠서 작성해야 할까?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;수요코딩회 팀 회의에서도 나온 이야기이고, 계속 고민하는 부분임. 기회가 된다면 시도해보고 싶다.&lt;&#x2F;li&gt;
&lt;li&gt;어차피 AI에 맡기고 결과를 분석할 거면, 요구사항 분석&#x2F;학습&#x2F;프롬프트 설계에 집중하고 하나의 에이전트로 개발하는 것도 협업이 아닌가 싶음.&lt;&#x2F;li&gt;
&lt;li&gt;역할 분배나 개발에서의 컨플릭 해결도 결국 AI를 많이 활용하게 될 텐데, 이렇다면 굳이 코드를 나눠야 하는 이유가 있을까?&lt;&#x2F;li&gt;
&lt;li&gt;이동석 코치님도 Week 5 발제 때 비슷한 이야기를 하셨음.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;koeotaimeun-jaju-haja&quot;&gt;코어타임은 자주 하자&lt;&#x2F;h3&gt;
&lt;p&gt;이번 주는 코어타임을 어쩌다 보니 월,화에 몰아서 하게 되었음.&lt;&#x2F;p&gt;
&lt;p&gt;수요코딩회에서는 1시간 간격으로 싱크를 맞추면서 자연스럽게 동료학습이 이루어졌는데, 회고하면서 생각해보니 코어타임도 비슷한 역할을 한다고 생각함.&lt;&#x2F;p&gt;
&lt;p&gt;이번에 알고리즘 시간에 동료학습이 잘 안 된 원인 중 하나가 코어타임을 몰아서 한 것이 아닐까 싶음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tim-peurojegteueseoyi-camyeo-bangsig-jeonhwan&quot;&gt;팀 프로젝트에서의 참여 방식 전환&lt;&#x2F;h3&gt;
&lt;p&gt;이동석 코치님 커피챗을 통해 Week 2~3처럼 자료를 정리해서 미리 제공하는 방식이 좋지 않다는 피드백을 받았고, 동의하게 되었음.&lt;&#x2F;p&gt;
&lt;p&gt;또한 이번 주차에서 대부분의 팀이 리액트를 안 써봤는데도 과제를 잘 구현한 걸 보면, 꼭 잘 아는 사람이 개입해야만 잘되는 것도 아니었다. 너무 걱정해서 자료를 미리 준비하거나 알려줄 필요는 없다고 느꼈다.&lt;&#x2F;p&gt;
&lt;p&gt;이 부분은 더 고민해 보고 다음 커피챗에서도 논의해 볼 예정.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;haegsim-yeogryang-mogpyo-hoego&quot;&gt;핵심 역량 목표 회고&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;잘 된 점:&lt;&#x2F;strong&gt; 몇 주간의 시행착오를 거치면서 문제 푸는 방법이나 양에서 적절한 지점을 찾았다고 생각함.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;고민:&lt;&#x2F;strong&gt; 목표 달성률은 높은데, 대부분 개인 학습 중심이고 팀원들과 함께 성장하는 내용이 부족함.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;다음 주차에 시도할 것:&lt;&#x2F;strong&gt; 핵심 역량 목표에 팀 차원의 목표를 하나 이상 포함하되, 단순 자료 제공과 같은 방식은 지양하기.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Week 03: 컴퓨팅 사고로의 전환</title>
          <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week03/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week03/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week03/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-oebu-jaryo-eobsi-seonhyeong-jaryogujo-jeongryeol-bunhaljeongbog-algorijeum-guhyeonhagi&quot;&gt;목표 1. 외부 자료 없이 선형 자료구조, 정렬&#x2F;분할정복 알고리즘 구현하기&lt;&#x2F;h3&gt;
&lt;p&gt;관련 역량: 구현, 품질, 설계&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;구현 대상은 자료구조(스택, 큐, 덱, 연결 리스트)와 알고리즘(병합 정렬, 퀵 정렬, 이진 탐색, 분할정복)이다.&lt;&#x2F;p&gt;
&lt;p&gt;주차 초반에 기본 구현을 마치고, 이후 제한 시간을 두고 문제 풀이 또는 핵심 기능을 재구현하는 방식으로 진행한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;기본 구현을 마친 후, 연결 리스트와 힙을 외부 자료 없이 구현할 수 있도록 반복 연습했다. 병합&#x2F;퀵 정렬도 마찬가지로 반복 구현했다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;연결 리스트, 병합&#x2F;퀵 정렬은 문제없이 구현 가능해졌다. 퀵&#x2F;병합 정렬의 개념이 예상보다 어렵지 않아서 체감 난이도가 낮았다.&lt;&#x2F;p&gt;
&lt;p&gt;힙은 연습량이 부족해서 아직 불완전하다. 남에게 설명할 수 있을 정도까지 추가 복습이 필요하다. 현재 코스의 작업을 유지하는 선에서 지금까지 배운 알고리즘을 가볍게 복습해 볼 계획이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-2-manheun-algorijeum-munjereul-jeobhago-pulgi&quot;&gt;목표 2. 많은 알고리즘 문제를 접하고 풀기&lt;&#x2F;h3&gt;
&lt;p&gt;Week 2에는 한 문제에 너무 많은 시간을 할당했다. 알고리즘 자체의 이해가 아닌 특정 유형의 풀이에 시간을 오래 쓰는 건 비효율적이다.&lt;&#x2F;p&gt;
&lt;p&gt;관련 역량: 문제해결, 학습 민첩성, AI 활용&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyehoeg-1&quot;&gt;계획&lt;&#x2F;h4&gt;
&lt;p&gt;문제당 30분 제한 시간 타이머를 설정한다. 소요 시간과 사고 흐름(접근 방식, 막힌 지점)을 주석으로 기록하고, 시간 내 해결한 문제 수를 기록하여 Week 02 대비 개선 여부를 확인한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;매번 타이머를 켜고 작업하는 습관을 들이려 했으나, 외부 요인으로 멈추거나 끄는 걸 잊어서 정확한 측정이 어려웠다.&lt;&#x2F;p&gt;
&lt;p&gt;각 문제 파일별로 기록용 템플릿을 추가해서 문제 풀이 흐름을 메모했다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 템플릿 예시&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# =============================================&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 문제: 그래프, DFS, BFS - 점프왕 쩰리 (백준 실버4)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 링크: https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;16173&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# AI 사용 횟수:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# AI 사용 방법:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 목표 시간: 15분&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 실제 시간:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 1. 초기 접근&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 2. 풀이 전략&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 3. 막힌 점 &#x2F; 실수&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 유형: [접근법] [구현] [엣지케이스] [최적화]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;# 4. 최종 코드&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; sys&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;접근법 자체는 맞았지만, 구현 실수를 찾는 데 시간이 많이 소모되는 경우가 있었다(예: 뱀 문제).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-mic-pideubaeg-1&quot;&gt;결과 및 피드백&lt;&#x2F;h4&gt;
&lt;p&gt;이전보다 문제당 소요 시간은 줄었지만, 뱀 문제처럼 반나절이 걸린 경우도 있었다.&lt;br &#x2F;&gt;
다만 디버깅을 통한 원인 파악 경험은 필요하므로, 구현 정확도와 목표 동작을 명확히 정의해 전체 해결 속도를 높이고, 디버깅 자체를 줄이기보다 문제 정의를 명확히 해 디버깅 시간을 줄여야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;템플릿을 쓰니 문제 풀이 이후에 접근 방식이나 사고 과정을 복기하기 좋았다.&lt;&#x2F;p&gt;
&lt;p&gt;하지만 Jungle Bell 개발에 시간을 써서 전 주차에 비해 문제를 푸는 양은 거의 동일했다(이건 아래 회고에서 설명).&lt;&#x2F;p&gt;
&lt;p&gt;AI 기반 분석에서 다음과 같은 피드백이 나왔는데, 정리하여 다음 주 계획에 반영 예정이다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;예제를 대충 보는 경향이 있으므로 여러 예제를 손으로 돌려보며 다양한 케이스를 고려할 것.&lt;&#x2F;li&gt;
&lt;li&gt;분석은 맞는데 구현 시 조건을 놓치므로 지문 조건을 주의 깊게 보면서 코딩할 것.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;csapp-ostep-seuteodi&quot;&gt;CSAPP &#x2F; OSTEP 스터디&lt;&#x2F;h3&gt;
&lt;p&gt;이진혁 님이 만든 스터디에 참여했다. 이런 책 스터디는 처음 해보는데, 서로 놓친 부분을 짚어주는 과정에서 이해도가 올라가서 좋았다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sijun-yang.com&#x2F;jungle&#x2F;jungle-cs&#x2F;&quot;&gt;CS 스터디 정리&lt;&#x2F;a&gt;도 작성 중. 책 내용을 그대로 정리하는 게 아니라, 따로 찾아본 내용이나 스터디 때 인상 깊었던 주제를 정리하고 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gongyu-jeongriyong-noteu-jagseong&quot;&gt;공유&#x2F;정리용 노트 작성&lt;&#x2F;h3&gt;
&lt;p&gt;팀원들이 아는 게 많아서 딱히 정리해서 공유할 만한 게 없었다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;3978a33fac695169d432f66b01f40d6a&quot;&gt;[Jungle My Note | W03] Mini-Redis 준비 자료&lt;&#x2F;a&gt;: 프로젝트 개발을 위해 각자 공부하면 도움될 만한 리스트&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;12847d4010c1dbb8a28744a1731abdc9&quot;&gt;[Jungle My Note | W03] LinkedList 구현&lt;&#x2F;a&gt;: 개인적으로 사용하는 범용 링크드리스트 구현&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;hyeobeob&quot;&gt;협업&lt;&#x2F;h3&gt;
&lt;p&gt;지난 주차와 달리 다들 알고리즘을 아는 상태여서, 처음 목표로 잡았던 잦은 자료 공유를 지킬 필요가 없었다.&lt;br &#x2F;&gt;
그래서 협업 목표는 팀 상황에 따라 유동적으로 가져가는 게 좋겠다는 생각을 했다.&lt;&#x2F;p&gt;
&lt;p&gt;첫 스크럼 전에 협업 목표를 미리 정하는 건 큰 의미가 없을 것 같다. 세우더라도 시간 엄수 같은, 어디서나 적용 가능한 목표 정도가 적절해보인다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;suyokodinghoe&quot;&gt;수요코딩회&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;minimi&quot;&gt;3주차 수요코딩회의 목표는 미니 Redis를 구현하는 것이었다.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;팀원들이 최대한 이해할 수 있도록 기능 구현을 줄이고 코드를 최소한으로 유지했는데, 이게 효과적이었는지는 잘 모르겠다.&lt;&#x2F;p&gt;
&lt;p&gt;돌이켜 보면, 요구사항과 엣지케이스를 깊게 파고들면서 구현 원리를 이해하는 방향이 더 나았을 것 같다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;추가&#x2F;삭제 요청이 네트워크 문제로 꼬이는 경우&lt;&#x2F;li&gt;
&lt;li&gt;악의적 사용자의 트래픽 부하&lt;&#x2F;li&gt;
&lt;li&gt;잘못된 포맷 검증&lt;&#x2F;li&gt;
&lt;li&gt;영속성을 제공하더라도 디스크 장애가 발생할 때의 처리&lt;&#x2F;li&gt;
&lt;li&gt;Redis가 왜 빠른지, RDB나 MongoDB도 내부적으로 메모리를 쓰는데 왜 더 느린지&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;이런 고민을 통해 Redis의 실제 구현과 비교하면서, 일부 기능이라도 딥다이브해서 정확하게 구현해보는 게 더 깊은 이해로 이어졌을 것이다.&lt;br &#x2F;&gt;
개발을 배우는 거지 얕게 훑으려는 게 아니니까, 내부 원리를 CS 지식과 연결해서 배우는 시간으로 활용했으면 어땠을까 하는 아쉬움이 있다.&lt;&#x2F;p&gt;
&lt;p&gt;3번째 팀이라 앞 팀의 구현 관련 질문이 많아서 넘어갔지만, 안 그랬으면 구현도 부족하고 깊은 이해도 없다는 평가를 받았을 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;다음에는 코드 자체에 집중하기보다 구현 원리를 이해하고, AI에게 설명하면서 검증하는 방식이 더 높은 효율을 보여주지 않을까 싶다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;idongseog-kocinim-ban-jeonce-pideubaeg-memo&quot;&gt;이동석 코치님 반 전체 피드백 메모&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;발표는 여러 사람이 번갈아가면서 할 것&lt;&#x2F;li&gt;
&lt;li&gt;기술뿐 아니라 협업이나 회고 관련 경험도 함께 이야기하기&lt;&#x2F;li&gt;
&lt;li&gt;듣는 사람을 위한 발표 연습 (폰트 크기, 배경 설명, 텍스트보다 시각적 자료 위주)&lt;&#x2F;li&gt;
&lt;li&gt;12 Factor 같은 현대 서버 원칙이 반영되었는지 확인 (특히 로그, 보안)&lt;&#x2F;li&gt;
&lt;li&gt;프로젝트를 하면서&#x2F;끝난 후 본인의 강점과 선택의 이유를 정리하기&lt;&#x2F;li&gt;
&lt;li&gt;AI는 소화할 수 있는 만큼만 활용할 것. 안 그러면 남는 게 없다.&lt;br &#x2F;&gt;
수요코딩회는 AI를 활용한 학습과 경험을 위한 자리이지, AI에 의존하는 것이 목적이 아니다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;jungle-bell-culsiwa-sigan-gwanri&quot;&gt;Jungle Bell 출시와 시간 관리&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;jungle-bell&quot;&gt;Jungle Bell&lt;&#x2F;a&gt;이라는 서비스를 만들었는데, 반응이 좋았다.&lt;br &#x2F;&gt;
같은 반에서 팀을 하지 않았던 분들도 설치해서 문의해주셔서 감사했다. 유지보수를 꾸준히 해야겠다는 생각이 든다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 만드는 게 재밌어서 시간을 많이 쏟아버렸고, 알고리즘 목표를 달성하지 못했다.&lt;br &#x2F;&gt;
실 사용자가 있는 서비스를 만드는 경험은 좋지만, 정글 코스에 집중하지 못하는 건 문제다.&lt;&#x2F;p&gt;
&lt;p&gt;개선 방안: 다음 주에는 태스크를 작게 쪼개서, 점심 시간이나 필수 학습 시간 외에만 개발하고, 그 외에는 알고리즘에 집중하도록 할 계획.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>CS 공부 내용 정리</title>
          <pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-cs/</link>
          <guid>https://sijun-yang.com/jungle/jungle-cs/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-cs/">&lt;p&gt;CSAPP, OSTEP를 읽으면서 이론적 지식을 공부하는 것도 좋지만, 실제 세계에서 어떤 식으로 동작하는가... 도 많이 궁금해하는 편이라 같이 메모하려고 함.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;csapp&quot;&gt;CSAPP&lt;&#x2F;h1&gt;
&lt;h3 id=&quot;1-2-mogjeogpaileun-eoddeohge-yeongyeoldoeneunga-ringkeoneun-eoddeohge-dongjaghaneunga&quot;&gt;1.2 - 목적파일은 어떻게 연결되는가? 링커는 어떻게 동작하는가?&lt;&#x2F;h3&gt;
&lt;p&gt;근데 이거 7장에 나오는 듯? 너무 딥하게 팔 필요는 없고 이런 이미지 정도로만 생각하고 있어도 충분해보임.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cass-kul.github.io&#x2F;exercises&#x2F;3-functions-stack&#x2F;calling-conventions-solution.png&quot; alt=&quot;img&quot; &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cass-kul.github.io&#x2F;exercises&#x2F;3-functions-stack&#x2F;&quot;&gt;출처: CASS&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;관련 자료&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;just-live.tistory.com&#x2F;entry&#x2F;CSAPP-7%EC%9E%A5-%EC%99%84%EC%A0%84-%EC%A0%95%EB%B3%B5-712713-%EA%B3%B5%EC%9C%A0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC%EC%9D%98-%ED%95%B5%EC%8B%AC-%EA%B8%B0%EC%88%A0-PIC-GOT-PLT&quot;&gt;[CSAPP 7장 완전 정복] 7.12 공유 라이브러리의 핵심 기술 - PIC, GOT, PLT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2011&#x2F;11&#x2F;03&#x2F;position-independent-code-pic-in-shared-libraries&quot;&gt;Position Independent Code (PIC) in shared libraries - Eli Bendersky&#x27;s website&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2013&#x2F;07&#x2F;09&#x2F;library-order-in-static-linking&quot;&gt;Library order in static linking - Eli Bendersky&#x27;s website&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1-4-keompyuteo-cpuneun-siljero-eoddeohge-saenggyeossneunga&quot;&gt;1.4 - 컴퓨터&#x2F;CPU는 실제로 어떻게 생겼는가?&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;gh&#x2F;koktlzz&#x2F;ImgBed@master&#x2F;20220811214041.png&quot; alt=&quot;img&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;이런 구조는 많이 보는데, 그래서 실제로 어떻게 생겼나?&lt;&#x2F;p&gt;
&lt;h4 id=&quot;keompyuteo&quot;&gt;컴퓨터&lt;&#x2F;h4&gt;
&lt;p&gt;I&#x2F;O Bridge가 나온 모델은 상대적으로 현대적인 모델이라 볼 수는 없었고, 단순한 Ben Eater를 보면 도움이 된다.&lt;&#x2F;p&gt;
&lt;p&gt;실제 구현해보려면 하드웨어를 만지는 것보다는 코드로 구현하는 Nand2Tetris를 하는게 좋을 듯 하다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;austinmorlan.com&#x2F;posts&#x2F;8bit_breadboard&#x2F;media&#x2F;third_build_1.jpg&quot; alt=&quot;img&quot; &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;austinmorlan.com&#x2F;posts&#x2F;8bit_breadboard&#x2F;&quot;&gt;출처&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Word 크기가 CPU의 처리 단위에 의해 결정된다는 점이 실물에서도 그대로 드러난다.
8-bit CPU이므로 한 번에 8-bit만 처리할 수 있고, 메모리 주소 공간도 그에 맞게 제한된다.&lt;&#x2F;p&gt;
&lt;p&gt;명령어 역시 8-bit로 구성되어 있다. &quot;ben eater 8 bit computer instruction set&quot;으로 검색하면 확인할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;한 클럭에 하나의 신호만 전송하므로, 위 이미지의 버스 배선도 실제로 8개의 선으로 이루어져 있다. 이 원리 자체는 현대 프로세서에서도 동일하다(버스 폭이 넓어졌을 뿐이다).&lt;&#x2F;p&gt;
&lt;p&gt;관련 자료&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;HyznrdDSSGM?si=t2DG6zrMPjV9eYiR&quot;&gt;Ben Eater의 8-bit 컴퓨터 영상.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;다른 사람이 구현한 Ben Eater 컴퓨터의 simulation도 있다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtube.com&#x2F;playlist?list=PLm-Y-XGnluLx03nwuHnrcUPWYckpLSYwv&amp;amp;si=xNTAcSINmkUUfRGM&quot;&gt;영상&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.instructables.com&#x2F;8BIT-COMPUTER&#x2F;&quot;&gt;LOGISIM 시뮬레이터 파일 소개&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chijoon-study&#x2F;B-major-study&#x2F;wiki&#x2F;Nand2Tetris-%EC%96%91%EC%8B%9C%EC%A4%80&quot;&gt;Nand2Tetris 개인적으로 정리한 자료&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Nand2Tetris ALU 회로 예시 &lt;img src=&quot;https:&#x2F;&#x2F;preview.redd.it&#x2F;nand2tetris-alu-in-digital-sim-v0-6tkacrgbdqa91.jpg?width=1970&amp;amp;format=pjpg&amp;amp;auto=webp&amp;amp;s=09996646183df034d3adc4f991e5350f4ba02886&quot; alt=&quot;img&quot; &#x2F;&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;beneater&#x2F;comments&#x2F;vvouna&#x2F;nand2tetris_alu_in_digital_sim&#x2F;&quot;&gt;출처&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;컴퓨터는 아주 간단하게 보면 정해진대로 전기 회로를 보내면, 클럭마다 메모리(레지스터,RAM)에 값을 쓰는걸 반복할 뿐인 기계이다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;cpu&quot;&gt;CPU&lt;&#x2F;h4&gt;
&lt;p&gt;실제 8bit의 CPU는 이렇게 생겼다. 버스도 8개 사용하는거 볼 수 있음.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;davidmjc.github.io&#x2F;6502&#x2F;cd.svg&quot; alt=&quot;img&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;davidmjc.github.io&#x2F;6502&#x2F;bcd.svg&quot; alt=&quot;img&quot; &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;davidmjc.github.io&#x2F;6502&#x2F;&quot;&gt;출처&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.visual6502.org&#x2F;&quot;&gt;visual6502.org&lt;&#x2F;a&gt;에서 JS로 시뮬레이션도 가능하다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;beoseu-i-o-bridge&quot;&gt;버스, I&#x2F;O Bridge&lt;&#x2F;h4&gt;
&lt;p&gt;CPU의 내부 데이터 경로는 기본적으로 워드 크기(32-bit, 64-bit 등)에 맞춰져 있지만, 외부 I&#x2F;O 버스(PCIe, USB, SPI 등)는 독자적인 데이터 폭과 프로토콜을 가진다.&lt;br &#x2F;&gt;
I&#x2F;O Bridge(버스 컨트롤러)가 이 차이를 변환한다. 복잡한 버스 컨트롤러는 펌웨어가 있는 경우도 있음.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;keompyuteoneun-wae-2jinsuinga-hadeuweeowa-gwanryeonhaeseo&quot;&gt;컴퓨터는 왜 2진수인가? 하드웨어와 관련해서&lt;&#x2F;h4&gt;
&lt;p&gt;최근 CSAPP를 읽다가 하드웨어 관련 내용을 보면서 예전에 봤던 영상이 떠올랐다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=H-jxTzFrnpg&quot;&gt;CD가 어떤 방식으로 동작하는지 간단하게 설명하는 영상이다.&lt;&#x2F;a&gt;
CD 표면에는 pit(홈)과 land(평면) 구조가 있는데, 레이저가 이를 지나가면 반사되는 빛의 세기가 달라진다. 이 차이를 센서가 감지해 전기 신호로 변환한다.&lt;&#x2F;p&gt;
&lt;p&gt;CD가 대부분 일회용인 이유도 여기에 있다. 기록할 때 물리적으로 구조를 바꿔버리기 때문이다.
HDD도 비슷하게 물리적 상태를 이용하지만 방식은 다르다. 디스크 표면에 자기장을 부여해 그 방향으로 0과 1을 구분하고, 이를 다시 바꿀 수 있기 때문에 여러 번 읽고 쓰기가 가능하다.&lt;&#x2F;p&gt;
&lt;p&gt;이 이야기는 결국 왜 컴퓨터가 2진수를 사용하는가를 설명하는 현실적인 비유로도 볼 수 있다.
컴퓨터가 다루는 수학은 이진수지만, 실제 물리 세계의 신호는 연속적인 값이다.&lt;&#x2F;p&gt;
&lt;p&gt;문제는 현실 세계의 하드웨어(전압, 물리적 디스크 등)에는 항상 노이즈(noise)가 존재한다는 점이다. 그래서 이를 안정적으로 처리하기 위해 여유 구간(noise margin)을 두고 신호를 구분한다. 이때 상태 수가 많아질수록 구분이 어려워지기 때문에, 두 상태로 나누는 방식이 가장 안정적이고 단순한 설계가 된다.&lt;&#x2F;p&gt;
&lt;p&gt;즉 다른 방식이 물리적으로 불가능한 것은 아니지만, 공학적으로 효율이 떨어지기 때문에 대부분의 컴퓨터가 2진 시스템을 사용한다고 볼 수 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-7-unyeongcejeneun-hadeuweeoreul-gwanrihanda&quot;&gt;1.7 - 운영체제는 하드웨어를 관리한다.&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;cusanghwa-reieo&quot;&gt;추상화 레이어&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;velog.velcdn.com&#x2F;images&#x2F;bgshin13&#x2F;post&#x2F;5c5f0298-4eda-49a3-882d-150a324e6d64&#x2F;image.png&quot; alt=&quot;img&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;기존에는 그림 1.10처럼 단순한 구조로만 이해하고 있었는데, 그림 1.11의 관점이 더 인상적이었다.&lt;&#x2F;p&gt;
&lt;p&gt;운영체제는&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I&#x2F;O 장치를 파일(file)로,&lt;&#x2F;li&gt;
&lt;li&gt;가상 메모리를 파일(I&#x2F;O 장치) + 물리 메모리로,&lt;&#x2F;li&gt;
&lt;li&gt;프로세스(process)는 프로세서와 가상 메모리(메모리 + I&#x2F;O)로 추상화한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;이걸 단순한 계층 구조로도 볼 수 있지만, 추상화 레이어로 해석할 수도 있다.&lt;&#x2F;p&gt;
&lt;p&gt;가상 메모리는 파일과 메모리를 합쳐서 메모리가 무한한 것처럼 추상화하고,
프로세스는 프로세서와 가상 메모리를 사용하여 무한한 독립된 공간인 것처럼 추상화된다.&lt;&#x2F;p&gt;
&lt;p&gt;이런 적으로 생각해본 적 없었는데 이게 인상 깊었다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jangci-pail&quot;&gt;장치 파일&lt;&#x2F;h4&gt;
&lt;p&gt;커널이 하드웨어와 유저레벨 중간에서 추상화를 제공해준다는 것의 좋은 예시.&lt;&#x2F;p&gt;
&lt;p&gt;라즈베리파이는 GPIO, I2C, SPI 같은 하드웨어에 &lt;code&gt;&#x2F;sys&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;dev&lt;&#x2F;code&gt; 같은 값을 쓰면,&lt;br &#x2F;&gt;
바로 LED가 켜지고 꺼지는 등의 반응을 볼 수 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;boan-gwanjeom&quot;&gt;보안 관점&lt;&#x2F;h4&gt;
&lt;p&gt;운영체제는 유저 레벨과 커널 레벨을 분리하여 역할을 나눈다.
이는 시스템 안정성과 보안을 확보하기 위한 구조이다.&lt;&#x2F;p&gt;
&lt;p&gt;이러한 구조의 중요성을 보여주는 사례로 2024년 CrowdStrike 장애가 있다.&lt;&#x2F;p&gt;
&lt;p&gt;해당 사건은 커널 모드에서 동작하는 보안 드라이버가 자동 업데이트 과정에서 오류를 포함하게 되면서 발생하였다.
그 결과 해당 소프트웨어를 사용하는 다수의 Windows 시스템이 동시에 다운되며 전산망이 마비되었다.&lt;&#x2F;p&gt;
&lt;p&gt;이 사례는 커널 레벨 코드에 문제가 발생할 경우 시스템 전체에 치명적인 영향을 줄 수 있음을 보여주며,
따라서 일반 프로그램이 커널에 직접 접근하지 못하도록 분리하는 것이 왜 중요한지 설명해준다.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;ostep&quot;&gt;OSTEP&lt;&#x2F;h1&gt;
&lt;h3 id=&quot;posix-glibc-alabogi&quot;&gt;POSIX, glibc 알아보기&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;UNIX는 Bell Labs에서 시작됨&lt;&#x2F;li&gt;
&lt;li&gt;이후 여러 회사&#x2F;기관이 각자 UNIX 변형을 만듦 → 호환성 문제 발생&lt;&#x2F;li&gt;
&lt;li&gt;이를 해결하려고 IEEE가 POSIX라는 표준을 정의&lt;&#x2F;li&gt;
&lt;li&gt;Linux는 UNIX가 아니라 Unix-like OS이며 POSIX를 따르는 방향으로 설계됨
&lt;ul&gt;
&lt;li&gt;Linux는 POSIX를 완전히 준수하지 않지만, glibc 등을 통해 POSIX 호환 환경을 제공한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;POSIX는 API, 동작 방식, 규칙을 명세한다. (정확한 명세를 위한 용어 정의도 있다.)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;glibc(글립씨, GNU C Library)는 C 표준 라이브러리이면서 POSIX API를 구현하고 GNU 확장 기능까지 포함한다.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;거의 대부분의 GNU&#x2F;Linux 배포판에서 glibc를 사용한다.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;macOS는 Unix 계열(OS X&#x2F;Darwin 기반)이며 POSIX를 상당 부분 준수하지만 완전한 호환은 아니다. 따라서 glibc를 사용하지 않고, 자체 libc(libSystem)를 사용한다.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;그래서 glibc는 유저레벨의 구현이고, pthread_create 같은 함수는 시스템 콜이 아니다.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;pthread_create는 내부적으로 clone() 시스템 콜을 사용하여 스레드를 생성하고, 필요 시 mmap() 등을 이용해 스택 메모리를 할당한다.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;weonjayeonsan-seupinrag-myutegseu-semapo-alabogi&quot;&gt;원자연산, 스핀락, 뮤텍스, 세마포 알아보기&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;AI로 정리된 내용임. 시간 관계상 다듬지는 못했는데, 나중에 시간나면 다듬기.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;atomic-instruction&quot;&gt;atomic instruction&lt;&#x2F;h4&gt;
&lt;p&gt;atomic instruction: 하드웨어가 제공하는 원자적 연산. 실행 도중 다른 코어가 끼어들 수 없음을 하드웨어 레벨에서 보장한다.&lt;&#x2F;p&gt;
&lt;p&gt;대표적인 것들:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;test-and-set (TAS)&lt;&#x2F;strong&gt;: 메모리 값을 1로 세팅하면서 이전 값을 리턴. x86의 &lt;code&gt;xchg&lt;&#x2F;code&gt;가 이에 해당.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;compare-and-swap (CAS)&lt;&#x2F;strong&gt;: 메모리 값이 expected와 같을 때만 new로 교체. x86의 &lt;code&gt;lock cmpxchg&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;load-linked &#x2F; store-conditional (LL&#x2F;SC)&lt;&#x2F;strong&gt;: ARM, RISC-V 계열. 두 명령어 쌍으로 atomicity를 보장.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;fetch-and-add (FAA)&lt;&#x2F;strong&gt;: 값을 atomic하게 증가. x86의 &lt;code&gt;lock xadd&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;전부 결국 이 하드웨어 atomic instruction 위에 쌓여 있다. OSTEP이 여러 가지를 나열하는 이유는 각각의 &lt;strong&gt;표현력&lt;&#x2F;strong&gt;(expressive power)과 성능 특성이 다르기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;예를 들어 TAS로 스핀락은 쉽게 만들지만, lock-free 큐 같은 건 CAS 없이는 사실상 못 만든다. CAS가 TAS보다 표현력이 강하다. 그리고 LL&#x2F;SC는 ABA 문제에서 CAS보다 유리하다.&lt;&#x2F;p&gt;
&lt;p&gt;OSTEP이 이걸 다 보여주는 건 &quot;종류가 많아서&quot;가 아니라, 각각이 풀 수 있는 문제의 범위가 다르기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lock-based vs Lock-free에서의 차이:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Lock-based: TAS든 CAS든 뭘 쓰든 상관없다. 어차피 lock 잡고 → critical section → unlock 패턴이니까, TAS 하나로 충분하다.&lt;&#x2F;li&gt;
&lt;li&gt;Lock-free: CAS가 사실상 필수다. 이유는 lock-free의 핵심 패턴이 &quot;현재 상태를 읽고, 새 상태를 계산하고, 바뀌지 않았을 때만 반영&quot;이기 때문이다. 이 조건부 쓰기가 CAS다. TAS는 조건 없이 무조건 덮어쓰니까 이 패턴을 표현할 수 없다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;전형적인 lock-free 패턴:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;do&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    old &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; load&lt;&#x2F;span&gt;&lt;span&gt;(ptr);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    new &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; compute&lt;&#x2F;span&gt;&lt;span&gt;(old);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;CAS&lt;&#x2F;span&gt;&lt;span&gt;(ptr, old, new));&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 실패하면 재시도&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;TAS로는 이 &quot;old가 아직 유효한지 확인&quot;하는 부분을 표현할 방법이 없다.&lt;&#x2F;p&gt;
&lt;p&gt;이론적 근거는 Herlihy (1991)의 consensus number 개념이다. TAS의 consensus number는 2로, 2개 스레드까지만 wait-free consensus를 풀 수 있다. CAS는 consensus number가 ∞여서 임의의 N개 스레드에 대해 lock-free&#x2F;wait-free 자료구조를 구현할 수 있다. 이게 CAS가 근본적으로 더 강력한 연산인 이유다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;참고: Herlihy, M. (1991). &quot;Wait-free synchronization.&quot; &lt;em&gt;ACM Transactions on Programming Languages and Systems&lt;&#x2F;em&gt;, 13(1), 124–149.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;seupinrag-myutegseu-semapo&quot;&gt;스핀락, 뮤텍스, 세마포&lt;&#x2F;h4&gt;
&lt;p&gt;계층 구조:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;하드웨어 atomic instructions  (TAS, CAS, LL&#x2F;SC, FAA)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ↓ 이걸로 구현&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      스핀락&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ↓ 이걸로 구현 (+ OS sleep&#x2F;wakeup 메커니즘)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    뮤텍스 &#x2F; 세마포어&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ↓ 이걸로 구현&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;고수준 동기화 (condition variable, barrier, rwlock 등)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h5 id=&quot;1-seupinrag-spinlock&quot;&gt;1. 스핀락 (Spinlock)&lt;&#x2F;h5&gt;
&lt;p&gt;가장 기본적인 lock. atomic instruction 하나로 구현 가능하다. lock을 못 잡으면 &lt;strong&gt;busy-wait&lt;&#x2F;strong&gt;(무한루프)하면서 계속 시도한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TAS 기반 스핀락 (가장 단순한 형태):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; flag;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 0 = 사용 가능, 1 = 잠김&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; spinlock_t&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 이전 값이 1이면 누가 잡고 있는 것 → 재시도&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; store만 하면 됨 (atomic store)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;test_and_set(&amp;amp;flag)&lt;&#x2F;code&gt;은 flag를 1로 세팅하고 이전 값을 리턴한다. 이전 값이 0이었으면 내가 lock을 잡은 것이고, 1이었으면 누군가 이미 잡고 있는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;x86 실제 구현 (GCC inline asm):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;__sync_lock_test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; GCC built-in: xchg 명령어로 컴파일됨&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    __sync_lock_release&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; flag = 0 + memory barrier&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;CAS 기반 스핀락:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;__sync_bool_compare_and_swap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; flag가 0일 때만 1로 바꾸기 시도&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; spin_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;spinlock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    __sync_lock_release&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;CAS로도 스핀락을 만들 수 있지만, TAS로 충분하다. CAS를 쓴다고 스핀락이 더 좋아지지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;스핀락의 문제점:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CPU 낭비&lt;&#x2F;strong&gt;: lock을 못 잡으면 while 루프를 돌면서 CPU 사이클을 소모한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;단일 코어에서 최악&lt;&#x2F;strong&gt;: lock을 잡은 스레드가 스케줄링되어야 unlock할 수 있는데, 대기 스레드가 CPU를 점유하고 있으면 그게 안 된다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;공정성 없음&lt;&#x2F;strong&gt;: 어떤 스레드가 먼저 lock을 잡을지 보장이 없다. starvation 가능.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;그럼 언제 쓰나?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;critical section이 매우 짧을 때 (수십~수백 나노초)&lt;&#x2F;li&gt;
&lt;li&gt;멀티코어 환경에서 context switch 비용보다 spinning이 싼 경우&lt;&#x2F;li&gt;
&lt;li&gt;인터럽트 핸들러 등 sleep할 수 없는 컨텍스트 (커널 내부)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Linux 커널은 스핀락을 광범위하게 사용한다. &lt;code&gt;spin_lock()&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;spin_unlock()&lt;&#x2F;code&gt; 함수가 그것.&lt;br &#x2F;&gt;
참고: Love, R. &lt;em&gt;Linux Kernel Development&lt;&#x2F;em&gt;, 3rd ed. Chapter 10.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;개선: ticket lock&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;기본 스핀락의 공정성 문제를 해결한 변형. 은행 번호표 시스템과 동일하다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; next_ticket;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 다음 번호표&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; now_serving;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 현재 서비스 중인 번호&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; ticket_lock_t&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; ticket_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;ticket_lock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; my_ticket &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; fetch_and_add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;next_ticket&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 번호표 뽑기&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;now_serving&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span&gt; my_ticket)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 내 차례 올 때까지 대기&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; ticket_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;ticket_lock_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;lock) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    lock&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;now_serving&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 다음 번호 호출&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;FIFO 순서가 보장되므로 starvation이 없다.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h5 id=&quot;2-myutegseu-mutex&quot;&gt;2. 뮤텍스 (Mutex)&lt;&#x2F;h5&gt;
&lt;p&gt;스핀락 + OS의 sleep&#x2F;wakeup 메커니즘. lock을 못 잡으면 busy-wait 대신 &lt;strong&gt;스레드를 재운다&lt;&#x2F;strong&gt; (sleep queue에 넣는다). lock이 풀리면 OS가 대기 스레드를 깨운다.&lt;&#x2F;p&gt;
&lt;p&gt;핵심: 뮤텍스 내부에서도 sleep queue를 조작하는 부분은 임계 영역이다. 이 부분은 짧은 스핀락으로 보호한다. 즉, &lt;strong&gt;뮤텍스 내부에 스핀락이 있다.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;개념적 구현:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; flag;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;             &#x2F;&#x2F; 0 = 사용 가능, 1 = 잠김&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; guard;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;            &#x2F;&#x2F; 내부 스핀락 (flag와 queue 조작 보호용)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;    queue_t&lt;&#x2F;span&gt;&lt;span&gt; wait_queue;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;   &#x2F;&#x2F; 대기 스레드 큐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; mutex_t&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; mutex_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;mutex_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;m) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 내부 스핀락 획득&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;       &#x2F;&#x2F; lock 획득 성공&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; 내부 스핀락 해제&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        queue_push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;, current_thread);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;      &#x2F;&#x2F; 내부 스핀락 해제&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        park&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;            &#x2F;&#x2F; OS 호출: 현재 스레드를 재움&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; mutex_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;mutex_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;m) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;queue_empty&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;)) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;       &#x2F;&#x2F; 대기자 없으면 그냥 해제&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        unpark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;queue_pop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 대기자 깨움&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; flag는 1 유지 — 깨어난 스레드가 lock을 이어받음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;이 구조가 OSTEP Chapter 28에서 설명하는 &lt;code&gt;park()&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;unpark()&lt;&#x2F;code&gt; 기반 lock이다. Solaris의 실제 메커니즘을 단순화한 것.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;왜 내부 스핀락(guard)이 필요한가?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&quot;sleep하면 되지, 왜 안에 스핀락이 또 있나?&quot;라는 의문이 생길 수 있다. 이유는 뮤텍스 자체의 상태(flag, wait_queue)를 조작하는 코드가 &lt;strong&gt;그 자체로 임계 영역&lt;&#x2F;strong&gt;이기 때문이다. guard 없이 구현하면 어떤 일이 벌어지는지 보자.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;guard 없는 잘못된 구현:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; mutex_lock_broken&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;mutex_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;m) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;          &#x2F;&#x2F; ① flag 확인&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;             &#x2F;&#x2F; ② flag 세팅&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        queue_push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;, current_thread);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; ③ 대기 큐에 등록&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        park&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;                                       &#x2F;&#x2F; ④ sleep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Race 1: flag 확인과 세팅 사이에 끼어들기 (두 스레드가 동시에 lock 획득)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;스레드 A                        스레드 B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;─────────                      ─────────&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;① flag == 0 확인 (true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ← 여기서 컨텍스트 스위치 →&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                ① flag == 0 확인 (true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                ② flag = 1 (lock 획득)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;② flag = 1 (lock 획득)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;둘 다 flag가 0인 것을 보고 둘 다 lock을 잡는다. 상호 배제 실패.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;그러면 flag를 CAS로 바꾸면 되지 않나?&quot; → flag 자체는 해결되지만, 그다음 문제가 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Race 2: lost wakeup — 깨우기 신호가 허공으로 날아간다&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Race 1은 CAS로 해결했다. 하지만 CAS가 실패한 후 &quot;큐에 등록하고 잠드는&quot; 과정에 또 다른 틈이 있다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; mutex_lock_still_broken&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;mutex_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;m) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;CAS&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;flag&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; flag는 atomic하게 처리&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; lock 획득&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; CAS 실패 — 누군가 lock을 잡고 있으므로 잠들어야 한다&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    queue_push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;m&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;, current_thread);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; ③ 큐에 등록&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ← 아직 잠들지 않았다! 이 틈이 문제다&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    park&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;                                       &#x2F;&#x2F; ④ 실제로 잠듦&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;핵심은 ③과 ④ 사이의 틈이다. 큐에 이름을 올렸지만 아직 &lt;code&gt;park()&lt;&#x2F;code&gt;는 호출하지 않은 순간이 존재한다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;스레드 A (lock 시도)              스레드 B (unlock)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;─────────────────               ──────────────&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;CAS 실패 (flag == 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;queue_push(A)  ← 큐에 등록됨&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ← 여기서 컨텍스트 스위치 →&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                queue에서 A를 pop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                unpark(A)  ← 깨우기 신호 전송!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  하지만 A는 아직 안 잠들었다.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  신호는 허공으로 사라진다.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                flag = 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;park()  ← A가 이제야 잠듦&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          깨워줄 스레드는 이미 지나갔다.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          → A는 영원히 잠든다&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;B가 &lt;code&gt;unpark(A)&lt;&#x2F;code&gt;를 호출한 시점에 A는 아직 &lt;code&gt;park()&lt;&#x2F;code&gt;를 호출하지 않은 상태다. &lt;code&gt;unpark()&lt;&#x2F;code&gt;는 잠들어 있지 않은 스레드에게는 효과가 없으므로 신호가 유실된다. 이후 A가 &lt;code&gt;park()&lt;&#x2F;code&gt;를 호출하면 다시 깨워줄 스레드가 없으므로 영원히 블록된다. 이것이 lost wakeup 문제다.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;CAS 실패 확인 → 큐 등록 → sleep&quot; 이 세 단계 사이에 다른 스레드가 끼어들 수 있기 때문에 발생한다. 그래서 이 세 단계를 하나의 원자적 구간으로 묶어야 하고, 그 역할을 하는 것이 guard 스핀락이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;guard가 하는 일을 정리하면:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guard가 보호하는 구간 (mutex_lock):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ┌─ flag 확인&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    │  flag 세팅 또는&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    │  queue에 현재 스레드 추가&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    └─ guard 해제 (→ 이후 park)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guard가 보호하는 구간 (mutex_unlock):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ┌─ queue 확인&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    │  queue에서 스레드 pop + unpark 또는&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    │  flag = 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    └─ guard 해제&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;lock과 unlock 양쪽 모두에서 guard를 잡으므로, lock 측의 &quot;flag 확인 + queue 추가&quot;와 unlock 측의 &quot;queue pop + unpark&quot;가 겹칠 수 없다. Race 1과 Race 2가 모두 차단된다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;guard 스핀락은 왜 문제가 안 되나?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;guard가 보호하는 구간은 flag 확인 + queue 조작뿐이라 매우 짧다 (수십 나노초). 이 짧은 구간에서만 spinning하니까 CPU 낭비가 사실상 없다. 실제 critical section(사용자 코드)에서는 sleep한다. 즉 뮤텍스의 spinning은 &quot;사용자의 critical section&quot;에 대한 것이 아니라, &quot;뮤텍스 자체의 내부 상태 조작&quot;에 대한 것이다. 이 구간은 고정적으로 짧으므로 스핀락의 단점(CPU 낭비)이 사실상 발생하지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Linux의 futex 기반 뮤텍스:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;실제 Linux에서 &lt;code&gt;pthread_mutex_lock()&lt;&#x2F;code&gt;은 futex (fast userspace mutex) 위에 구현된다. fast path는 유저스페이스에서 CAS 한 번으로 끝나고, contention이 있을 때만 커널로 진입해서 sleep한다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pthread_mutex_lock() 동작:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. CAS(&amp;amp;mutex-&amp;gt;state, 0, 1) 시도  ← 유저스페이스, 시스템콜 없음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. 성공 → lock 획득. 끝.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3. 실패 → futex(FUTEX_WAIT) 시스템콜 → 커널이 스레드를 재움&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4. 나중에 unlock에서 futex(FUTEX_WAKE) → 커널이 깨움&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;contention이 없으면 시스템콜이 아예 발생하지 않는다. 이것이 futex가 빠른 이유.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;참고: Franke, H., Russell, R., &amp;amp; Kirkwood, M. (2002). &quot;Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux.&quot; Ottawa Linux Symposium.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;POSIX pthread 뮤텍스 사용 예시:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;lt;pthread.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt; &amp;lt;stdio.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;pthread_mutex_t&lt;&#x2F;span&gt;&lt;span&gt; lock &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; PTHREAD_MUTEX_INITIALIZER;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; shared_counter &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;arg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 100000&lt;&#x2F;span&gt;&lt;span&gt;; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        pthread_mutex_lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;lock);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        shared_counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;          &#x2F;&#x2F; critical section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        pthread_mutex_unlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;lock);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    pthread_t&lt;&#x2F;span&gt;&lt;span&gt; t1, t2;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    pthread_create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;, worker,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    pthread_create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;, worker,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    pthread_join&lt;&#x2F;span&gt;&lt;span&gt;(t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    pthread_join&lt;&#x2F;span&gt;&lt;span&gt;(t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;counter = &lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, shared_counter);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 항상 200000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;뮤텍스 없이 &lt;code&gt;shared_counter++&lt;&#x2F;code&gt;를 하면 race condition으로 200000보다 작은 값이 나온다. &lt;code&gt;counter++&lt;&#x2F;code&gt;는 load → add → store 3단계이므로 원자적이지 않다.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h5 id=&quot;3-semapoeo-semaphore&quot;&gt;3. 세마포어 (Semaphore)&lt;&#x2F;h5&gt;
&lt;p&gt;뮤텍스의 일반화. 내부에 &lt;strong&gt;정수 카운터&lt;&#x2F;strong&gt;를 가지고, 이 값이 0 이하면 대기한다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sem_wait()&lt;&#x2F;code&gt; (= P 연산, down): 카운터 감소. 0 이하면 sleep.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;sem_post()&lt;&#x2F;code&gt; (= V 연산, up): 카운터 증가. 대기 스레드가 있으면 깨움.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;뮤텍스와의 핵심 차이:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;특성&lt;&#x2F;th&gt;&lt;th&gt;뮤텍스&lt;&#x2F;th&gt;&lt;th&gt;세마포어&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;내부 값&lt;&#x2F;td&gt;&lt;td&gt;0 또는 1&lt;&#x2F;td&gt;&lt;td&gt;임의의 정수 N&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;소유권&lt;&#x2F;td&gt;&lt;td&gt;lock한 스레드만 unlock 가능&lt;&#x2F;td&gt;&lt;td&gt;아무 스레드나 post 가능&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;용도&lt;&#x2F;td&gt;&lt;td&gt;상호 배제&lt;&#x2F;td&gt;&lt;td&gt;상호 배제 + 순서 제어 + 리소스 카운팅&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;소유권 차이가 중요하다. 뮤텍스는 lock한 스레드가 반드시 unlock해야 한다. 세마포어는 스레드 A가 wait하고 스레드 B가 post할 수 있다. 이 특성 때문에 &lt;strong&gt;스레드 간 순서 제어&lt;&#x2F;strong&gt;(signaling)가 가능하다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;개념적 구현:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; value;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; guard;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;            &#x2F;&#x2F; 내부 스핀락&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;    queue_t&lt;&#x2F;span&gt;&lt;span&gt; wait_queue;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt; sem_t&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;s) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        queue_push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;, current_thread);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        park&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;           &#x2F;&#x2F; sleep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;s) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;test_and_set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        unpark&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;queue_pop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;wait_queue&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 대기자 깨움&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;이 구현은 OSTEP Chapter 31의 Zemaphore를 기반으로 단순화한 것.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;용도 1: 이진 세마포어 = 뮤텍스처럼 사용 (초기값 1)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span&gt; mutex;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;sem_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 초기값 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;     &#x2F;&#x2F; lock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; critical section&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;     &#x2F;&#x2F; unlock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;초기값이 1이므로 한 스레드만 진입 가능. 기능적으로 뮤텍스와 동일하지만, 소유권 검사가 없으므로 다른 스레드가 post할 수도 있다 (이건 보통 버그).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;용도 2: 순서 제어 (초기값 0)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;스레드 간 실행 순서를 강제할 때 사용. 뮤텍스로는 이걸 직접 할 수 없다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span&gt; order;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;sem_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;order,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 초기값 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; 스레드 A (먼저 실행되어야 할 작업)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;thread_a&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;arg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;A: 작업 완료&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;order);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;     &#x2F;&#x2F; &amp;quot;나 끝났어&amp;quot; 시그널&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; 스레드 B (A가 끝난 후 실행되어야 할 작업)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;thread_b&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;arg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;order);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;     &#x2F;&#x2F; A가 post할 때까지 여기서 대기&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;B: A 이후 작업 시작&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;B가 먼저 실행되더라도 &lt;code&gt;sem_wait()&lt;&#x2F;code&gt;에서 블록된다. A가 &lt;code&gt;sem_post()&lt;&#x2F;code&gt;를 호출해야 B가 진행된다. 이것이 &quot;외부에서 값 반환이 가능하므로 순서 보장 시 사용&quot;이라고 했던 것의 정확한 의미다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;용도 3: 리소스 카운팅 (초기값 N)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;동시에 N개까지 접근을 허용. 대표적 예: 커넥션 풀, bounded buffer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;&#x2F;&#x2F; bounded buffer (생산자-소비자 문제)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; BUFFER_SIZE&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span&gt; empty;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;   &#x2F;&#x2F; 빈 슬롯 수&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span&gt; full;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; 찬 슬롯 수&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;sem_t&lt;&#x2F;span&gt;&lt;span&gt; mutex;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;   &#x2F;&#x2F; 버퍼 접근 보호&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span&gt;[BUFFER_SIZE];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; fill &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;, use &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    sem_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;empty,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;, BUFFER_SIZE);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; 처음엔 전부 비어있음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    sem_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;full,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;             &#x2F;&#x2F; 처음엔 아무것도 없음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;    sem_init&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;producer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;arg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;empty);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;              &#x2F;&#x2F; 빈 슬롯 하나 확보&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;              &#x2F;&#x2F; 버퍼 접근 lock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;        buffer&lt;&#x2F;span&gt;&lt;span&gt;[fill]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        fill &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; (fill &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span&gt; BUFFER_SIZE;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;              &#x2F;&#x2F; 버퍼 접근 unlock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;full);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;               &#x2F;&#x2F; 찬 슬롯 하나 증가&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;consumer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;arg) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;full);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;               &#x2F;&#x2F; 찬 슬롯 하나 확보&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;        int&lt;&#x2F;span&gt;&lt;span&gt; val &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span&gt;[use];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        use &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; (use &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span&gt; BUFFER_SIZE;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mutex);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        sem_post&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;empty);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A0A1A7;font-style: italic;&quot;&gt;              &#x2F;&#x2F; 빈 슬롯 하나 증가&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;consumed: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #0184BC;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #50A14F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, val);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;empty&lt;&#x2F;code&gt;와 &lt;code&gt;full&lt;&#x2F;code&gt; 세마포어가 생산자와 소비자 간 흐름 제어를 담당한다. 버퍼가 꽉 차면 생산자가 블록되고, 비면 소비자가 블록된다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;이 패턴은 Dijkstra(1965)가 세마포어를 처음 제안할 때의 핵심 예제이며, OSTEP Chapter 31에서도 동일하게 다룬다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;jeongri&quot;&gt;정리&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;스핀락:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 구현: atomic instruction + busy-wait loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 대기 방식: CPU를 소모하며 반복 확인 (spinning)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 사용처: 커널 내부, 짧은 critical section, sleep 불가능한 컨텍스트&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;뮤텍스:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 구현: 내부 스핀락 + OS sleep&#x2F;wakeup (futex 등)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 대기 방식: lock 못 잡으면 sleep → unlock 시 wakeup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 소유권: lock한 스레드만 unlock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 사용처: 유저스페이스 상호 배제의 기본&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;세마포어:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 구현: 정수 카운터 + 내부 스핀락 + OS sleep&#x2F;wakeup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 대기 방식: 카운터 ≤ 0이면 sleep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 소유권: 없음 (아무나 post 가능)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 사용처: 상호 배제, 순서 제어, 리소스 카운팅&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;참고 문헌:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Arpaci-Dusseau, R. &amp;amp; Arpaci-Dusseau, A. &lt;em&gt;Operating Systems: Three Easy Pieces (OSTEP)&lt;&#x2F;em&gt;. Chapters 28–31.&lt;&#x2F;li&gt;
&lt;li&gt;Herlihy, M. (1991). &quot;Wait-free synchronization.&quot; &lt;em&gt;ACM TOPLAS&lt;&#x2F;em&gt;, 13(1).&lt;&#x2F;li&gt;
&lt;li&gt;Dijkstra, E. W. (1965). &quot;Cooperating Sequential Processes.&quot; Technical Report EWD-123.&lt;&#x2F;li&gt;
&lt;li&gt;Love, R. (2010). &lt;em&gt;Linux Kernel Development&lt;&#x2F;em&gt;, 3rd ed. Addison-Wesley.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
</description>
      </item>
      <item>
          <title>Week 02: 컴퓨팅 사고로의 전환</title>
          <pubDate>Thu, 12 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-week02/</link>
          <guid>https://sijun-yang.com/jungle/jungle-week02/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-week02/">&lt;h2 id=&quot;haegsim-yeogryang-mogpyo&quot;&gt;핵심 역량 목표&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;문제해결: 주어진 문제를 정의하고 논리적으로 해결하는 능력&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;알고리즘 문제의 입력&#x2F;출력&#x2F;제약 조건을 정확히 파악하고,&lt;br &#x2F;&gt;
실버~골드 수준의 백준 문제를 스스로 분석하여 해결 전략을 수립할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;설계: 효율적이고 확장 가능한 시스템 구조를 기획&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;시간 복잡도를 이해하고, 사용한 알고리즘과 구현의 시간 복잡도를 올바르게 평가할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;구현: 설계된 내용을 실제로 동작하는 코드로 작성&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;정렬, 정수론 등의 기초 알고리즘을 직접 구현하고, 재귀 함수와 백트래킹 문제를 올바르게 구현할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;품질: 버그 없는 안정적인 코드 및 테스트 작성&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;제약 조건의 엣지 케이스에 대한 예외 처리를 고려하여 코드를 작성할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;유지보수: 가독성이 좋고 수정이 용이한 코드 작성&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;함수 단위로 로직을 분리하고, 직관적으로 이해 가능한 네이밍을 사용한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;협업: 팀원과 소통하며 시너지를 내는 과정&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;데일리 스크럼으로 목표와 진행 상황을 공유하고, 매일 푼 과제를 공유&#x2F;리뷰하며 지식을 나눈다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;태도: 자기주도적인 학습과 과제에 대한 몰입(집요함)&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;문제를 풀고 넘어가는 게 아닌, 여러 번 반복하여 체화한다. 특히, 틀린 문제는 2번 이상 반복 풀이한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;비즈니스 이해: 서비스의 가치와 사용자 입장을 고려하는 시각&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;알고리즘 복잡도가 실제 서비스 성능(응답 시간, 메모리 사용)에 미치는 영향을 이해하고 설명할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;AI 활용: AI 도구를 활용하여 생산성을 극대화하는 능력&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;AI는 이론 공부와 풀이 피드백 용도로만 사용한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[공부 - AI 활용] → [풀이 - AI 금지] → [1차 피드백 - AI 금지] → [2차 피드백 - AI 활용]&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;학습 민첩성: 새로운 기술이나 개념을 빠르게 습득하는 능력&lt;&#x2F;strong&gt;
&lt;ul&gt;
&lt;li&gt;정수론과 백트래킹 관련 개념을 4일 내에 습득하고 설명할 수 있을 정도로 공부한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;wil-what-i-learned&quot;&gt;WIL (What I Learned)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mogpyo-1-jeongsuron-jaegwi-baegteuraeking-munjepuli-yeogryang-hwagbo&quot;&gt;목표 1. 정수론&#x2F;재귀&#x2F;백트래킹 문제풀이 역량 확보&lt;&#x2F;h3&gt;
&lt;p&gt;자신 없는 정수론&#x2F;재귀&#x2F;백트래킹 문제를 중급 난이도까지 풀 수 있는 이론 지식, 문제 풀이 능력을 가지기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jeobgeun&quot;&gt;접근&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;이번 주 과제 중 중급 난이도 이하의 모든 문제를 일요일까지 풀기. 제한시간 30분.&lt;&#x2F;li&gt;
&lt;li&gt;못 푼 문제를 리스트업하고 해당 문제의 개념을 공부 후, 2번 이상 복습.&lt;&#x2F;li&gt;
&lt;li&gt;비슷한 요구사항의 문제를 찾아 더 풀이하기.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;gwajeong&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;29cca5b67540bbc5ad093466cc26c33c&quot;&gt;백트래킹 문제의 대표적인 순열&#x2F;조합 유형 구현 방법을 복습하기 위해 AI를 활용해 정리 자료를 생성&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;9a13d85d258baf912b10d411f0e22033&quot;&gt;2026&#x2F;03&#x2F;09 - Recursion 특강 정리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;5e2a7c120bcc1c2e8d4ef3d915cf8e0c&quot;&gt;하노이의 탑 정리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;난이도 중 이하 모든 문제 2번 이상 반복 풀이&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;gyeolgwa&quot;&gt;결과&lt;&#x2F;h4&gt;
&lt;p&gt;정수론은 출제 빈도와 응용 범위를 고려해 우선순위를 낮게 두었고, 그만큼 아직 부족한 부분이 남아 있다. &lt;del&gt;확장 유클리드 호제법은 이해조차 못했다.&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;p&gt;하노이의 탑, 완전탐색, 순열&#x2F;조합, N-Queen 등의 백트래킹&#x2F;재귀 문제를 풀 수 있게 되었다.&lt;br &#x2F;&gt;
반복 풀이를 통해 재귀&#x2F;백트래킹의 공통 패턴과 구현 방식을 체득한 것이 이번 주차의 가장 큰 성과다.&lt;&#x2F;p&gt;
&lt;p&gt;문제 조건 분석과 접근 방식 선택(base case 설정 등)은 아직 미숙하지만, 충분한 시간이 주어지면 구현 자체에서 실수하는 경우는 거의 없어졌다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mogpyo-2-gwaje-gongyu-ribyureul-tonghan-tim-seongjang&quot;&gt;목표 2. 과제 공유&#x2F;리뷰를 통한 팀 성장&lt;&#x2F;h3&gt;
&lt;p&gt;팀원들과 공유하여 더 빠른 성장을 돕고, 다른 관점의 풀이를 보며 함께 성장하기.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jeobgeun-1&quot;&gt;접근&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;첫 스크럼에서 매일 푼 문제를 슬랙에 올리고 서로 리뷰하자고 제안했다.&lt;&#x2F;li&gt;
&lt;li&gt;여러 유용한 자료를 찾거나 준비하여 팀에게 전달했다.
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;dd3e23e99cec3675ae23b9df12556347&quot;&gt;코테 준비 노트 (기존에 정리했던 것)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;59d1ac76f435a494b77ad52a087ab053&quot;&gt;학습 계획 (신규 정리)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtube.com&#x2F;playlist?list=PLhQjrBD2T3817j24-GogXmWqO5Q5vYy0V&amp;amp;si=9453M0M1LxzzM_w1&quot;&gt;파이썬 + 프로그래밍 강의 추천 (링크)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;gwajeong-1&quot;&gt;과정&lt;&#x2F;h4&gt;
&lt;p&gt;매일 스크럼 시 슬랙을 통해 풀이 내역이 담긴 커밋 링크를 공유했다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;SW-AI-W02-05-TEMPLATE&#x2F;commits&#x2F;main&#x2F;?since=2026-03-06&amp;amp;until=2026-03-12&quot;&gt;2주차 커밋 내역 링크&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;코어타임에 문제 풀이를 공유하고, 팀원과 헷갈리는 개념에 대해 대화를 나눴다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gyeolgwa-1&quot;&gt;결과&lt;&#x2F;h4&gt;
&lt;p&gt;예상보다 각자의 알고리즘 문제 풀이에 많은 시간이 소요되었다.&lt;&#x2F;p&gt;
&lt;p&gt;그로 인해 팀원 간 공유나 협력이 원활하지 않았다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 공유한 자료들은 팀 내에서 유용하게 활용되고 있는 것으로 보인다.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;hoego&quot;&gt;회고&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;yeogryang-dalseongryul&quot;&gt;역량 달성률&lt;&#x2F;h3&gt;
&lt;p&gt;초기 목표를 얼마나 달성했는지를 기준으로 상&#x2F;중&#x2F;하로 구분.&lt;br &#x2F;&gt;
단, 해당 주차와 관련이 없거나 평가가 어려운 경우 N&#x2F;A로 표기.&lt;&#x2F;p&gt;
&lt;p&gt;어느 정도 주관적인 판단이 포함될 수 있음.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;#&lt;&#x2F;th&gt;&lt;th&gt;역량&lt;&#x2F;th&gt;&lt;th&gt;달성률&lt;&#x2F;th&gt;&lt;th&gt;설명&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;문제해결&lt;&#x2F;td&gt;&lt;td&gt;중&lt;&#x2F;td&gt;&lt;td&gt;골드 수준의 문제 분석 및 전략 수립은 아직 어려움.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;설계&lt;&#x2F;td&gt;&lt;td&gt;상&lt;&#x2F;td&gt;&lt;td&gt;대략적으로나마 시간 복잡도를 유추할 수 있음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;구현&lt;&#x2F;td&gt;&lt;td&gt;상&lt;&#x2F;td&gt;&lt;td&gt;개념을 이해한 경우, 구현 자체에는 문제 없었음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;품질&lt;&#x2F;td&gt;&lt;td&gt;하&lt;&#x2F;td&gt;&lt;td&gt;동일 문제를 반복 풀이하는 데 집중한 탓에 엣지케이스 판단 능력을 키우지 못했음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;유지보수&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;td&gt;2주차 내용과 관련성이 낮음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;협업&lt;&#x2F;td&gt;&lt;td&gt;하&lt;&#x2F;td&gt;&lt;td&gt;예상보다 잘 되지 않음. (후기에서 후술함)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;태도&lt;&#x2F;td&gt;&lt;td&gt;중&lt;&#x2F;td&gt;&lt;td&gt;문제 공유나 협업 측면에서는 잘 수행했으나 전반적으로 기대에 미치지 못함.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;8&lt;&#x2F;td&gt;&lt;td&gt;비즈니스 이해&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;td&gt;2주차 내용과 관련성이 낮음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;9&lt;&#x2F;td&gt;&lt;td&gt;AI 활용&lt;&#x2F;td&gt;&lt;td&gt;중&lt;&#x2F;td&gt;&lt;td&gt;잘 활용했지만, 힌트를 받는 방식이 더 좋았음. 처음 의도와 달라짐.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;10&lt;&#x2F;td&gt;&lt;td&gt;학습 민첩성&lt;&#x2F;td&gt;&lt;td&gt;중&lt;&#x2F;td&gt;&lt;td&gt;빠르게 학습하긴 했지만, 한 문제에 지나치게 시간을 소비하여 전체 진도가 느렸음.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;hugi&quot;&gt;후기&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;ibeon-ju-hwaldonge-daehan-pyeongga&quot;&gt;이번 주 활동에 대한 평가&lt;&#x2F;h4&gt;
&lt;p&gt;전반적으로 높은 목표를 설계했다는 느낌을 받았다. 또 시간 관리도 부족하다고 느꼈다.&lt;&#x2F;p&gt;
&lt;p&gt;협업도 예상보다 쉽지 않았다. 리뷰하기에는 본인 과제를 풀이하기에도 시간이 않지 않았다. 의도적으로 시간을 할당하는 등의 의식적인 노력이 필요할거 같음.&lt;&#x2F;p&gt;
&lt;p&gt;나에게는 준비 없는 구두 설명이 어려웠다. 자료 공유 방식이 더 효과적이였던 것 같음.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daeum-jue-sidohae-bol-geos&quot;&gt;다음 주에 시도해 볼 것&lt;&#x2F;h4&gt;
&lt;p&gt;문제당 시간 제한을 두고, AI 해설을 적극 활용하여 더 많은 유형에 노출되는 방식으로 전환한다.&lt;br &#x2F;&gt;
난이도를 올리기보다는 중급(실버~골드) 수준을 유지하면서 유형 폭을 넓히는 데 집중한다.&lt;&#x2F;p&gt;
&lt;p&gt;팀 기여 방식은 구두 설명보다 자료 공유가 더 효율적이고 내 강점에도 맞으므로, 자료 공유를 더 적극적으로 한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;wilyi-hyeongsige-daehan-hugi&quot;&gt;WIL의 형식에 대한 후기&lt;&#x2F;h4&gt;
&lt;p&gt;다른 사람들의 제출을 보니, 너무 핵심 역량 목표에 집중된 듯한 느낌을 받음.&lt;&#x2F;p&gt;
&lt;p&gt;별개로 나누어서 해야 할거 같음. 힉심 역량 파트를 줄이고, WIL은 말 그대로 배운 것들의 리스트가 나와야 할 듯.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;cuga-03-12-unyeongjin-titaim&quot;&gt;추가 — 03&#x2F;12 운영진 티타임&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;q-a-haegsim-yeogryang-mogpyoyi-yimi&quot;&gt;Q&amp;amp;A: 핵심 역량 목표의 의미&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Q&lt;&#x2F;strong&gt;: 핵심 역량 10가지에 대해 목표를 세우게 되는데, 알고리즘 주차의 경우 유지보수나 비즈니스 이해와 직접적 관련이 없어 보인다. 10개를 모두 작성해야 하는가? 어떤 항목을 중심으로 써야 할까?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A: 이동석 코치님&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;10가지를 모두 작성할 필요는 없다. 특정 주차에는 상대적으로 덜 중요한 역량이 있을 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 모든 핵심 역량은 중요하므로 각 역량과의 연결점을 고민해보면 좋겠다.&lt;br &#x2F;&gt;
여기서 배우는 것들은 실제 현장에서 필요한 역량이고, 어떤 식으로든 현실과 연결되는 부분이 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A: 김현수 코치님&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;핵심 역량 목표를 도입한 배경은, 이전 기수들이 많은 활동을 했음에도 이력서에 잘 드러나지 않는 점이 아쉬웠기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;따라서 몇 가지 역량에 집중해서 계획을 세우고 발전 과정을 기록하여, 성과가 가시적으로 드러나도록 하려는 의도다.&lt;&#x2F;p&gt;
&lt;p&gt;예를 들어, 알고리즘 주차를 완료했다고 해서 문제 해결 능력이 뛰어난 것은 아니다.
하지만 알고리즘 주차에서 문제 해결을 위한 구체적 목표를 세우고 달성한 기록이 있다면, 문제 해결 능력을 어필할 수 있다. 이력서 활용뿐 아니라, 목표가 있으면 스스로의 성장에도 도움이 될 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;항상 전부 채울 필요는 없지만, 이런 의도를 이해해주면 좋겠다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;saenggag-haegsim-yeogryang-mogpyoreul-eoddeon-sigeuro-seweoya-halgga&quot;&gt;생각: 핵심 역량 목표를 어떤 식으로 세워야 할까?&lt;&#x2F;h4&gt;
&lt;p&gt;이 답변과 Week2 WIL 작성 시의 생각을 종합했을 때 다음과 같은 결론을 세웠다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;최소 2~3개 이상의 핵심 역량 목표를 정한다.&lt;&#x2F;li&gt;
&lt;li&gt;수치화하거나 이전 상태와 비교 가능한 형태로 목표를 설정한다.&lt;&#x2F;li&gt;
&lt;li&gt;선택하는 역량은 한 영역에 치우치지 않고, 개인 역량과 협업 역량에서 각각 최소 1개 이상 포함한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;수치화&#x2F;비교 가능한 목표의 예:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;저번 주차 미해결 골드 문제를 이번 주차에 30분 내 독립 풀이. 전&#x2F;후 소요시간 기록.&lt;&#x2F;li&gt;
&lt;li&gt;엣지케이스 체크리스트 도입, Week 02 대비 1차 제출 정답률 비교 기록.&lt;&#x2F;li&gt;
&lt;li&gt;팀원 피드백 시간을 별도로 할당하여 N회 이상 실행. 팀 프로젝트 시 머지 컨플릭을 잘 해결하는 Skill.md 도입 등.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>정글 에세이: 퇴사하고 정글에 온 이유</title>
          <pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/jungle/jungle-essay/</link>
          <guid>https://sijun-yang.com/jungle/jungle-essay/</guid>
          <description xml:base="https://sijun-yang.com/jungle/jungle-essay/">&lt;p&gt;첫 번째 회사에서 약 1년 8개월의 일을 마무리하고 정글에 참여하게 되었다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keuraepeuton-jeonggeule-gayagessdago-dajimhan-iyu&quot;&gt;크래프톤 정글에 가야겠다고 다짐한 이유&lt;&#x2F;h2&gt;
&lt;p&gt;나는 광주소프트웨어마이스터고등학교를 다녔다. 학교에서는 팀 프로젝트 위주의 자습이 대부분이였고 이론이나 CS를 깊게 배우기 어려운 환경이었다.&lt;&#x2F;p&gt;
&lt;p&gt;이런 아쉬움에 개인적으로 OS나 CS 자료를 찾아 공부했는데, 어렵게 찾은 개념을 잘 정리해둔 글이 크래프톤 정글을 다니면서 쓴 글이라는 걸로 정글을 처음 알게 되었다.&lt;&#x2F;p&gt;
&lt;p&gt;정글을 찾아보니, 합숙 방식과 CS 위주의 커리큘럼이 매력적이었다. 특히 고등학교에서 기숙사 생활과 팀 프로젝트를 통해 빠르게 성장한 경험이 있어서 더 공감할 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;고등학교 졸업 후 바로 정글에 지원하고 싶었지만, 길어진 취준 생활이 두려워 도피성으로 부트캠프를 찾는 건 아닌지 의심이 들어 취업에 집중했다. 운이 좋게도 2025년 7월에 강남의 작은 스타트업에서 백엔드 개발자로 일을 시작했다.&lt;&#x2F;p&gt;
&lt;p&gt;그럼에도 CS 공부에 대한 욕심은 사라지지 않았다. 단순 구현만 가능한 개발자가 아니라, CS와 기본기를 바탕으로 빠른 기술 적응과 의사 결정이 가능한 개발자가 되어야 한다는 생각은 변하지 않았다. 특히 AI의 발전으로 이 생각은 더 강해졌다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5gaeweol-dongan-eodgo-sipeun-geos&quot;&gt;5개월 동안 얻고 싶은 것&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-gibongi&quot;&gt;1. 기본기&lt;&#x2F;h3&gt;
&lt;p&gt;CS나 자료구조 같은 기본기는 항상 필요하다고 생각하지만, 당장 티가 나는 지식이 아니다 보니 일하면서 공부하기 어려웠다. 이 기회에 확실하게 집중해서 학습하고자 한다.&lt;&#x2F;p&gt;
&lt;p&gt;커리큘럼 중 자료구조, 알고리즘, 운영체제와 컴퓨터 시스템은 더 집중해서 배울 생각이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-yeoreo-saramdeulgwa-tim-peurojegteu-gyeongheom&quot;&gt;2. 여러 사람들과 팀 프로젝트 경험&lt;&#x2F;h3&gt;
&lt;p&gt;소마고를 다니면서 팀 프로젝트를 해보았지만, 거의 정해진 팀원과 개발했고 시간 여유도 많았다.&lt;&#x2F;p&gt;
&lt;p&gt;정글에선 더 높은 난이도의 과제를 팀원들과 협력해보고, 만나보지 못했던 다양한 나이대와 배경의 사람들을 만나보고 싶다.&lt;br &#x2F;&gt;
특히 운영체제나 기본기에 관심이 많았지만 이야기할 사람이 없었는데, 여기서는 함께 이야기하면서 학습할 수 있어서 기대된다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;camyeohaneun-taedo&quot;&gt;참여하는 태도&lt;&#x2F;h2&gt;
&lt;p&gt;AI를 적극적으로 사용하면서 학습 능력의 저하를 많이 체감했다. 최대한 AI 없이, 고통스럽더라도 스스로 고민하며 학습하는 방식을 시도해 볼 생각이다.&lt;&#x2F;p&gt;
&lt;p&gt;원래 이런 방식을 선호하지만, 시간과 효율을 이유로 실천하지 못했다.&lt;br &#x2F;&gt;
첫 주차 미니 프로젝트를 하면서 하루 15시간 이상을 순수 작업에 쏟을 수 있는 환경이라는 걸 체감했고, 이 시간적 여유를 활용해 최대한 삽질을 많이 해볼 생각이다.&lt;br &#x2F;&gt;
이때가 아니면 언제 가능하겠나 싶다.&lt;&#x2F;p&gt;
&lt;p&gt;협업 관점에서는 실무&#x2F;개발 경험을 가진 사람이 많지 않아(최소한 이번 기수, 나의 반에서는) 이런 경험으로 알게 된 지식을 기반으로 많이 도움을 줄 수 있을 것 같다.&lt;br &#x2F;&gt;
머신러닝이나 딥러닝도 커리큘럼에 있는데, 전혀 해본 적이 없어서 이 파트에선 오히려 도움받는 입장이 되지 않을까 싶다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jeonggeuli-ggeutnan-huyi-na&quot;&gt;정글이 끝난 후의 나&lt;&#x2F;h2&gt;
&lt;p&gt;CS 기초가 탄탄하게 쌓여서 새로운 개념들을 쉽게 공부하고 배워나갈 수 있는 사람이 되었으면 좋겠다.&lt;&#x2F;p&gt;
&lt;p&gt;이를 기반으로 오픈소스에 기여하거나 난이도 있는 토이 프로젝트를 진행하며 개발 능력을 높여가고자 한다.&lt;br &#x2F;&gt;
(&lt;del&gt;그리고 가능하면 취업에도 성공하고&lt;&#x2F;del&gt;)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 2026년 2월</title>
          <pubDate>Sat, 28 Feb 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-2026-02/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-2026-02/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-2026-02/">&lt;p&gt;이번 달의 큰 이벤트는 크래프톤 정글 SW 12기 합격과 참여를 위한 첫 번째 회사의 퇴사이다.&lt;br &#x2F;&gt;
인수인계와 시험 준비에 많은 시간을 소요하여 자료 수집과 작업을 많이 하지 못했다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;llmeul-cib-wie-inswae-haneun-taalasyi-bangsig-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anuragk.com&#x2F;blog&#x2F;posts&#x2F;Taalas.html&quot;&gt;LLM을 칩 위에 &#x27;인쇄&#x27;하는 Taalas의 방식&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26896&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Taalas라는 스타트업이 Llama 3.1 8B 모델의 가중치를 하드웨어 칩의 트랜지스터로 직접 구현했다.&lt;&#x2F;p&gt;
&lt;p&gt;원래 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;xrath&#x2F;status&#x2F;2024680485629133053?s=20&quot;&gt;X에서&lt;&#x2F;a&gt; 먼저 알았는데 GeekNews에도 올라왔다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tokenpost.kr&#x2F;news&#x2F;tech&#x2F;332509&quot;&gt;TokenPost 기사&lt;&#x2F;a&gt;도 참고.&lt;&#x2F;p&gt;
&lt;p&gt;처음 보고 모델을 칩에 고정한다는 발상이 신선했는데, 생각해 보면 비슷한 사례가 이미 있다.&lt;&#x2F;p&gt;
&lt;p&gt;부동소수점 연산은 원래 소프트웨어로 처리하다가 CPU에 내장되었다.
ARM도 JavaScript의 부동소수점→정수 변환을 하드웨어 명령어(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.arm.com&#x2F;documentation&#x2F;dui0801&#x2F;l&#x2F;A64-Floating-point-Instructions&#x2F;FJCVTZS&quot;&gt;FJCVTZS&lt;&#x2F;a&gt;)로 넣었다.&lt;&#x2F;p&gt;
&lt;p&gt;자주 쓰이는 연산을 하드웨어에 옮기는 건 반복되어 온 패턴이지만, LLM이 가능할 거라고는 직관적으로 생각하지 못했던 부분이다.&lt;&#x2F;p&gt;
&lt;p&gt;속도가 비교도 안 되게 빠르다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;chatjimmy.ai&#x2F;&quot;&gt;데모 사이트&lt;&#x2F;a&gt;에서 직접 대화해 보면 체감할 수 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;baibeukodingyi-boan-munje-moltbook-haeking-geeknews-openclaw-makeudaun-agseongkodeu-geeknews&quot;&gt;바이브코딩의 보안 문제: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wiz.io&#x2F;blog&#x2F;exposed-moltbook-database-reveals-millions-of-api-keys&quot;&gt;MoltBook 해킹&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26371&quot;&gt;GeekNews&lt;&#x2F;a&gt;) | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;1password.com&#x2F;blog&#x2F;from-magic-to-malware-how-openclaws-agent-skills-become-an-attack-surface&quot;&gt;OpenClaw 마크다운 악성코드&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26579&quot;&gt;GeekNews&lt;&#x2F;a&gt;)&lt;&#x2F;h3&gt;
&lt;p&gt;MoltBook이 Supabase 설정 오류로 150만 개의 API 키, 35,000개 이상의 이메일, 비공개 메시지가 노출되었다.
RLS(Row Level Security)가 비활성화되어 누구나 전체 DB에 접근 가능한 상태였다.&lt;&#x2F;p&gt;
&lt;p&gt;OpenClaw 에이전트의 마크다운 악성코드 문제도 있었다.&lt;br &#x2F;&gt;
ClawHub의 인기 스킬이 마크다운 문서에 위장된 악성 링크를 포함하고 있었는데,
사람들이 마크다운 파일을 위험하다고 인식하지 않는 점을 노린 것이다.
이제는 텍스트 자체가 취약점이 될 수 있다는 사실을 인지해야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 두 사례는 별개의 이슈다.&lt;br &#x2F;&gt;
MoltBook의 사례를 예시로 OpenClaw가 위험하다는 식의 의견을 종종 보았는데, 이는 맞지 않는 말이다.&lt;&#x2F;p&gt;
&lt;p&gt;MoltBook은 기업가 Matt Schlicht가 코드를 직접 보지 않고 바이브코딩으로 만든 플랫폼이고, OpenClaw의 Peter Steinberger는 전 소프트웨어 엔지니어로 코드 구조를 설계하고 리뷰한다.&lt;br &#x2F;&gt;
OpenClaw의 악성코드 문제는 사칭 배포처에서 발생한 사건으로, 사람이 만든 소프트웨어라도 동일하게 발생할 수 있는 유형이다.&lt;br &#x2F;&gt;
또한 OpenClaw 자체 구조상 플랫폼 내부에서 개인정보가 유출되는 문제와는 직접적인 관련이 없다. 다만 OpenClaw는 AI에게 강력한 권한을 부여하는 도구이기 때문에, 이런 문제는 자연스러운 특성에 가깝다.&lt;&#x2F;p&gt;
&lt;p&gt;어쨌든 바이브코딩의 문제점을 잘 보여주는 사례다.
개인정보를 저장하고 관리하는 곳에 바이브코딩을 적용하는 게 올바른지는 확실히 고민해 봐야 한다.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;karpathy&#x2F;status&#x2F;2017442712388309406&quot;&gt;Andrej Karpathy도 보안 취약점&#x2F;해킹&#x2F;스팸&#x2F;조작 등의 이유로 사용을 비추하면서도, 대규모(15만+) 에이전트 네트워크를 만들어낸 건 흥미롭다고 평가했다.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-hangug-diseukodeu-caeneolyi-rust-for-linux-gwanryeon-geul-discord&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discord.com&#x2F;channels&#x2F;487203989830631435&#x2F;487203989830631438&#x2F;1476536789866123386&quot;&gt;Rust 한국 디스코드 채널의 Rust-for-Linux 관련 글 | Discord&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Linux Kernel v7.0-rc1 릴리즈와 함께 Rust 지원이 확대되었고, 실제 하드웨어 디바이스 지원을 위한 기능들이 추가되었다.
Linux Plumbers Conference 2025 분위기도 Rust 중심이었으며, 커널 개발 쪽에서 Rust 채택 흐름이 강해지는 상황이다.
커널 개발에 관심 있는 사람이라면 지금 Rust 기반 커널 개발 흐름에 참여하는 것도 좋다는 의견이 나왔다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2026nyeon-geunyang-postgresreul-sseuja-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tigerdata.com&#x2F;blog&#x2F;its-2026-just-use-postgres&quot;&gt;2026년, 그냥 Postgres를 쓰자&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26388&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;대부분의 기업은 PostgreSQL 하나로 충분하다는 주장이다.&lt;&#x2F;p&gt;
&lt;p&gt;AI 에이전트 시대에는 단일 DB 환경에서 빠르게 테스트하고 디버깅하는 것이 효율적이고,
백업&#x2F;모니터링&#x2F;보안 전략을 단일화하여 운영 비용을 줄일 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;PostgreSQL 확장 기능으로 검색(pg_textsearch), 벡터 검색(pgvector), 시계열(TimescaleDB), 문서(JSONB) 등을
전문 프로그램과 비교하여 거의 비슷한 성능을 낼 수 있다고 주장한다.&lt;&#x2F;p&gt;
&lt;p&gt;실무에서도 그런 통계 결과가 나올지 모르겠지만,
실제 데이터 시연 결과를 보여주고 증명하는 점에서 테스트해 보고 도입해 볼 만한 것 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stop-forwarding-errors-start-designing-them&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fast.github.io&#x2F;blog&#x2F;stop-forwarding-errors-start-designing-them&#x2F;&quot;&gt;Stop Forwarding Errors, Start Designing Them&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Rust에서 더 나은 에러 처리를 위해, 기계가 처리할 정보와 사람이 읽을 정보를 분리하자는 글.&lt;&#x2F;p&gt;
&lt;p&gt;예를 들어 기계용 정보로는 &lt;code&gt;ErrorKind&lt;&#x2F;code&gt; 열거형과 &lt;code&gt;ErrorStatus&lt;&#x2F;code&gt;를 통해 처리 방법, 재시도 가능 여부 등을 명시하고,
사람용 정보로는 &lt;code&gt;#[track_caller]&lt;&#x2F;code&gt;로 호출 위치를 자동으로 기록하며, 타입 시스템으로 모듈 경계에서 문맥 추가를 강제한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;aegsyeonbeiseu-actionbase-johayo-coegeun-bon-palroureul-wihan-deiteobeiseu-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kakao&#x2F;actionbase&quot;&gt;액션베이스(Actionbase) – 좋아요, 최근 본, 팔로우를 위한 데이터베이스&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26192&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;좋아요, 팔로우, 최근 본 항목 등 &quot;누가 무엇을 어떻게 했다&quot;라는 관계형 기능을 위한 카카오의 오픈소스 DB이다.&lt;br &#x2F;&gt;
쓰기 시점에 모든 데이터를 미리 계산하고 읽기는 단순 조회만 수행하여 빠르고 예측 가능한 성능을 제공한다.&lt;br &#x2F;&gt;
카카오톡 선물하기 위시 등 프로덕션 환경에서 분당 100만 건 이상의 요청을 처리 중이라고 한다.&lt;&#x2F;p&gt;
&lt;p&gt;회사에서 비슷한 걸 RDB로 만들어 본 적 있는데, 구현이나 유지보수가 어려웠다.&lt;br &#x2F;&gt;
나중에 비슷한 기능을 구현하게 될 수도 있다고 생각하는데, 이 프로젝트의 코드나 원리를 뜯어보면 적용할 수 있을 것 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;geu-oe-sujibhan-geul&quot;&gt;그 외 수집한 글&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.millert.dev&#x2F;&quot;&gt;&lt;strong&gt;Todd C. Miller – 30년 넘게 Sudo를 유지보수한 개발자&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26363&quot;&gt;GeekNews&lt;&#x2F;a&gt;): sudo가 30년간 한 명이 유지보수해 온 프로그램이라는 사실. sudo가 별도 프로그램이라는 것도 새삼 인식하게 되었다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;claude.com&#x2F;blog&#x2F;complete-guide-to-building-skills-for-claude&quot;&gt;&lt;strong&gt;Claude Skills 구축을 위한 완벽 가이드&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26328&quot;&gt;GeekNews&lt;&#x2F;a&gt;): Anthropic이 제공하는 33쪽 가이드. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;fa5d9cd0eb41d6f545c78121d620080c#file-the-complete-guide-to-building-skill-for-claude_kr-md&quot;&gt;마크다운 번역본&lt;&#x2F;a&gt;도 정리해 두었다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nesbitt.io&#x2F;2025&#x2F;12&#x2F;15&#x2F;how-i-assess-open-source-libraries.html&quot;&gt;&lt;strong&gt;How I Assess Open Source Libraries&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: 오픈소스 보안 컨설팅 전문가가 라이브러리를 채택할 때의 평가 기준을 소개하는 글.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;karpathy.github.io&#x2F;2026&#x2F;02&#x2F;12&#x2F;microgpt&#x2F;&quot;&gt;&lt;strong&gt;microgpt - 200줄 순수 파이썬으로 구현한 GPT 학습 및 추론&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26746&quot;&gt;GeekNews&lt;&#x2F;a&gt;): Andrej Karpathy가 외부 의존성 없이 200줄로 GPT 전체를 구현한 교육용 프로젝트.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;7UOdYxKW8pE?si=VrMhGoCAh8ViwkdA&quot;&gt;&lt;strong&gt;How I became a Linux Kernel Contributor&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: 한 커널 컨트리뷰터가 본인의 기여 여정을 소개하는 영상. 실제 커널 기여 시 전체적인 참여 흐름을 이해하는 데 도움이 될 듯하다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;samueleresca.net&#x2F;analysis-of-what-every-programmer-should-know-about-memory&#x2F;&quot;&gt;&lt;strong&gt;메모리 관련 자료 모음&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: &quot;What Every Programmer Should Know About Memory&quot; 요약 버전. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;samueleresca.net&#x2F;memory-management-optimizations-techniques&#x2F;&quot;&gt;메모리 최적화 기법&lt;&#x2F;a&gt;도 함께 참고.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.irregular.com&#x2F;publications&#x2F;vibe-password-generation&quot;&gt;&lt;strong&gt;LLM이 만든 비밀번호가 위험한 이유, 100비트처럼 보이지만 실제론 27비트&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26919&quot;&gt;GeekNews&lt;&#x2F;a&gt;): LLM은 근본적으로 토큰 생성기다. 따라서 인간과 마찬가지로 진정한 무작위성과는 거리가 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;jjalbeun-geul-ai-sidaeyi-hagseubgwa-olbareun-sayonge-daehan-gomin&quot;&gt;짧은 글: AI 시대의 학습과 올바른 사용에 대한 고민&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;ai-sidaeeseoyi-hagseub-neungryeoggwa-peurojegteu-gaebal-yiyog-jeoha&quot;&gt;AI 시대에서의 학습 능력과 프로젝트 개발 의욕 저하&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;research&#x2F;AI-assistance-coding-skills&quot;&gt;Anthropic 연구&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26364&quot;&gt;GeekNews&lt;&#x2F;a&gt;)에 따르면, AI에 작업을 전적으로 맡긴 개발자들은 퀴즈에서 17% 낮은 점수를 기록했다.
AI는 학습 측면에서는 그다지 도움이 되지 않을 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.marginalia.nu&#x2F;log&#x2F;a_132_ai_bores&#x2F;&quot;&gt;&quot;AI가 당신을 지루하게 만든다&quot;&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26832&quot;&gt;GeekNews&lt;&#x2F;a&gt;)라는 글에서도 말하듯, AI 중심의 개발 방식은 금방 흥미를 잃게 만들 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;나 역시 이 의견에 동의하는데, AI를 많이 사용할수록 결과물에 대한 애착이 줄어들고 장기적으로 이해도가 떨어진다는 느낌을 받았다.&lt;&#x2F;p&gt;
&lt;p&gt;따라서 의도적으로 AI 없이 코드를 작성하고 학습하는 과정을 만들어야 한다고 생각하고 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;eoddeohge-kodeureul-darueoya-halgga&quot;&gt;어떻게 코드를 다루어야 할까?&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adventures.nodeland.dev&#x2F;archive&#x2F;the-human-in-the-loop&#x2F;&quot;&gt;Node.js 메인테이너인 Matteo Collina&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26247&quot;&gt;GeekNews&lt;&#x2F;a&gt;)도 AI를 생산성 도구로 활용하되, 판단력과 책임은 포기하면 안 된다고 주장한다.&lt;&#x2F;p&gt;
&lt;p&gt;요즘 해커뉴스나 긱뉴스, 여러 오픈소스 커뮤니티에서 AI Slop의 남발로 인한 문제는 심심치 않게 접할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;하지만 AI 활용이 긍정적인 사례도 분명히 있다.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;devwrite.ai&#x2F;ko&#x2F;posts&#x2F;hwplibsharp-upstream-management&#x2F;&quot;&gt;hwplibsharp 업스트림 관리&lt;&#x2F;a&gt;에서는 AI가 포팅 코드를 작성하고 리뷰만으로 유지보수하는 방식을 소개한다.
이전에 본 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;new-blog.ch4n3.kr&#x2F;llm-found-security-issues-from-django-ko&#x2F;&quot;&gt;$5짜리 프롬프트로 $2,418짜리 취약점을 찾은 사례&lt;&#x2F;a&gt;도 좋은 영향을 주는 AI 활용 예시라고 생각한다.&lt;&#x2F;p&gt;
&lt;p&gt;이런 식으로 AI를 사용하되, 피해나 부담을 주지 않으면서 긍정적으로 활용하려는 자세가 필요한 듯하다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ai-gaebalyi-3gaji-johab&quot;&gt;AI 개발의 3가지 조합&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;simnalamburt&#x2F;status&#x2F;2019045989693419648&quot;&gt;X에서 본 글인데, 인간(의지&#x2F;의도 주입) + LLM(코드 생성) + 정적분석(타입체커, 린터, 자동테스트)&lt;&#x2F;a&gt;을 조합하는 구성이 좋다는 의견이다.&lt;br &#x2F;&gt;
좋은 패턴이라고 생각해서 시도해 볼 계획이다.&lt;&#x2F;p&gt;
&lt;p&gt;AI와 함께 개발한다면, 혼자가 아니라 다른 사람과 협업하는 것처럼 접근해야 한다.&lt;br &#x2F;&gt;
코드를 작성하는 주체가 여럿이므로 이런 구성을 기본으로 사용하는 게 올바르다고 생각한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jjalbeun-geul-functorwa-monadga-mueosinga&quot;&gt;짧은 글: Functor와 Monad가 무엇인가?&lt;&#x2F;h3&gt;
&lt;p&gt;참고한 글:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;evan-moon.github.io&#x2F;2024&#x2F;01&#x2F;30&#x2F;category-theory-for-programmers-0-preface&#x2F;&quot;&gt;카테고리 이론으로 설명하는 프로그래머를 위한 글&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;evan-moon.github.io&#x2F;2026&#x2F;02&#x2F;07&#x2F;monads-in-typescript&#x2F;&quot;&gt;TypeScript로 보는 Monad&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rosettalens.com&#x2F;s&#x2F;ko&#x2F;8bbc0343bf794c368287&quot;&gt;모나드는 포켓몬이다: 수학 없이 배우는 모나드 입문 - RosettaLens 번역본&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;정리한 핵심 개념:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Functor&lt;&#x2F;strong&gt;: &lt;code&gt;A =&amp;gt; B&lt;&#x2F;code&gt;를 적용하면서 컨텍스트는 불변. 현실의 사이드이펙트나 별도 기능을 의미하는 컨테이너로 실제 값(타입)을 감싸는 것.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monad&lt;&#x2F;strong&gt;: &lt;code&gt;A =&amp;gt; M[B]&lt;&#x2F;code&gt;를 적용하면서 컨텍스트를 합성. Monad는 Functor를 포함한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;: 계산의 성격이나 값의 추가 정보. Option(있거나 없음), List(여러 개), Future(대기 중) 등.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monad의 실용적 관점&lt;&#x2F;strong&gt;: 연산 중 컨테이너를 컨테이너로 감싸는 중첩 문제를 해결하기 위한 것.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monad의 함수적 관점&lt;&#x2F;strong&gt;: 숫자에 0을 더해도 값이 변하지 않듯, 어떤 컨테이너를 &lt;code&gt;pure&lt;&#x2F;code&gt;로 감싸고 다시 펴는 행위가 원래의 정보나 상태에 영향을 주지 않아야 한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monad 종류&lt;&#x2F;strong&gt;: Option, Either, List, IO, Future, State, Reader 등. 구현을 바꾸면 패턴을 유지하면서 동작을 변경할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;사실 하스켈 같은 순수 함수형에 가까운 언어를 사용해 본 경험이 거의 없어서, 이런 식으로 정보만 접하는 게 올바른지는 모르겠지만,
모나드에 대해서 실용적으로 적용할 수 있을 정도는 이해한 것 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zsh-starship-teomineol-hwangyeong-seting&quot;&gt;zsh + starship 터미널 환경 세팅&lt;&#x2F;h3&gt;
&lt;p&gt;zsh + &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;starship.rs&#x2F;guide&#x2F;&quot;&gt;starship&lt;&#x2F;a&gt;을 사용해 봤다.&lt;br &#x2F;&gt;
oh-my-zsh 대신 플러그인 &lt;code&gt;zsh-autosuggestions&lt;&#x2F;code&gt;, &lt;code&gt;zsh-syntax-highlighting&lt;&#x2F;code&gt;를 설치한 기본 zsh에 적용하였다.&lt;&#x2F;p&gt;
&lt;p&gt;스타일은 oh-my-zsh보다 취향에 맞아 만족하고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;참고한 자료:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;starship.rs&#x2F;guide&#x2F;&quot;&gt;starship 가이드&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.kreonet.net&#x2F;linux-guide&#x2F;z-51119446.html&quot;&gt;zsh 설정 참고&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;a3a8bf8083bc812855292ea63e7906f0&quot;&gt;dotfiles 예시&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cs146s-the-modern-software-developer-gangyi-jeongri&quot;&gt;CS146S: The Modern Software Developer 강의 정리&lt;&#x2F;h3&gt;
&lt;p&gt;1월에 소개했던 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;themodernsoftware.dev&#x2F;&quot;&gt;Stanford CS146S 강의&lt;&#x2F;a&gt;를 주차별로 정리했다.&lt;&#x2F;p&gt;
&lt;p&gt;다만 3주차부터는 시간이 없어서 실습을 하지 못했고, 자료에 대한 요약을 훑어보기만 했다. (&lt;del&gt;항상 이런 식으로 대충 마무리된다.&lt;&#x2F;del&gt;)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;8fa074151175bf0abfaebf75bf466b83&quot;&gt;Week 1: 정리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;5bcb1cf16552a710498bcb82f1dae54e&quot;&gt;Week 1 추가: Deep Dive into LLMs - Andrej Karpathy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;acc9bd7b1e6873f732650bf3ef2b590d&quot;&gt;Week 1 추가: AI Prompt Engineering - Anthropic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;631d4f38ecd05ab2e108cd54cf7b377f&quot;&gt;Week 2: 정리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;29d7463632f52881bcefe3d3f047994c&quot;&gt;Week 3: The AI IDE&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;d6b9d29d58d9a31c43596cc53d4c6be4&quot;&gt;Week 4: Coding Agent Patterns&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;e3ac9296c1d6132c1bf6e5e043972b4b&quot;&gt;Week 5: The Modern Terminal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;64bdac75e86d945c94ed93fd597291d6&quot;&gt;Week 6: AI Testing and Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;cac6eccfcb1a837c203d4f884d6eefff&quot;&gt;Week 7: Code Review&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;75e9ea1cb0086fc98748adf1a787ba80&quot;&gt;Week 8: Automated UI and App Building&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;5dabc0403905e35396919db98d337de6&quot;&gt;Week 9: Agents Post-Deployment&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;noteu-llm-tokeun-banbog-rupeu-ihae&quot;&gt;노트: LLM 토큰 반복 루프 이해&lt;&#x2F;h3&gt;
&lt;p&gt;LLM 공부를 하다 보니 원리가 궁금해져서 예전에 본 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;YVfIe1r5SNI&quot;&gt;뉴로사마 고장 영상&lt;&#x2F;a&gt;의 원인을 찾아보았다.&lt;&#x2F;p&gt;
&lt;p&gt;어떤 이유로 &quot;location&quot;의 선택 확률이 비정상적으로 높아지면, 출력된 &quot;location&quot;이 컨텍스트 윈도우에 누적되고,
컨텍스트에 &quot;location&quot;이 많을수록 다음 토큰으로 &quot;location&quot;을 선택할 확률이 더 높아져서 피드백 루프가 발생한다.&lt;&#x2F;p&gt;
&lt;p&gt;비달(개발자)은 뉴로(LLM 에이전트)에게 중립적인 단어를 계속 말하게 하여 컨텍스트 윈도우에서 &quot;location&quot;을 밀어내서 해결하였다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jjalbeun-saenggag&quot;&gt;짧은 생각&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;근황과 요즘 하는 생각&lt;&#x2F;p&gt;
&lt;p&gt;크래프톤 정글 SW 12기에 합격하였고, 참여를 위해 1년 8개월 정도 다닌 회사를 퇴사하게 되었다.&lt;br &#x2F;&gt;
주위에서 주워들은 정보로 보면 충분히 안정적이고 성장 가능성 있는 회사라고 생각하지만, 개인적인 성장에 대한 욕심이 있어 퇴사하게 되었다.&lt;&#x2F;p&gt;
&lt;p&gt;개발용으로 사용할 노트북을 중고로 저렴하게 구했다.&lt;br &#x2F;&gt;
배터리 상태 100%인 MacBook M1 Pro, RAM 32GB &#x2F; SSD 512GB 모델을 150만 원에 구매했다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ayangweb&#x2F;BongoCat&quot;&gt;BongoCat&lt;&#x2F;a&gt;이라고 데스크톱에서 고양이가 마우스 위치와 타이핑을 따라하는 앱이 재미있고 귀여워 보여 설치했다.&lt;br &#x2F;&gt;
가끔 유튜브에서 비슷한 기능을 버튜버들이 쓰는 걸 볼 수 있고, 나는 작게 우측 하단에 띄워놓으면서 쓰고 있다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 2026년 1월</title>
          <pubDate>Sat, 31 Jan 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-2026-01/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-2026-01/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-2026-01/">&lt;p&gt;이번 달에는 정규표현식 내부 구조, 비동기 모델, 스레드 메모리 위치 같은 기술 관련 내용을 파봤다. 기술 관련 글을 읽다가 궁금해진 것들이다.
그리고 여러 개인, 기업, 교육기관에서 AI 활용 능력을 다룬 글들이 많이 눈에 띄었다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;the-missing-semester-of-your-cs-education&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;missing.csail.mit.edu&#x2F;&quot;&gt;The Missing Semester of Your CS Education&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;MIT에서 진행하는 강의다. CS 수업과 달리 명령줄, 에디터, 버전 관리 시스템 등 개발자가 매일 사용하는 도구를 효율적으로 활용하는 방법에 초점을 둔다. 강의 자료와 영상은 인터넷에 공개되어 있어 외부 사용자도 자유롭게 학습할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;Git, 디버깅, Shell 활용, dotfiles 관리, 기본적인 보안 개념 등 실무에서 알아두면 좋은 주제들을 넓고 얕게 정리해 준다. 관심 있는 주제만 골라서 봐도 이해하는 데 상관없어 부담 없이 볼 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;2026년 강의는 현재 촬영 중이며, 2020년 이후 새롭게 공개되는 강의이다. LSP와 AI 기반 도구 관련 내용이 추가되고 Shell이나 Vim의 비중은 줄어드는 등, 개발 환경의 변화가 비교적 잘 반영되고 있는 듯하다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;73-programming-project-ideas-to-inspire-and-challenge-you-hackernews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codecrafters.io&#x2F;blog&#x2F;programming-project-ideas&quot;&gt;73 Programming Project Ideas to Inspire and Challenge You&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46439027&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;직접 구현해볼 수 있는 73개의 프로그래밍 프로젝트 아이디어와 참고 자료를 정리한 글이다.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub에서 유명한 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;codecrafters-io&#x2F;build-your-own-x&quot;&gt;build-your-own-x&lt;&#x2F;a&gt; 레포가 있는데, CodeCrafters에서 운영하고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;CodeCrafters는 Redis, Git 같은 유명한 프로젝트를 직접 만들어보는 서비스를 제공한다. 관심 가는 프로젝트들이 있어서 시간 나면 시도해볼 생각이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;regular-expression-matching-can-be-simple-and-fast-hackernews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;swtch.com&#x2F;~rsc&#x2F;regexp&#x2F;regexp1.html&quot;&gt;Regular Expression Matching Can Be Simple And Fast&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=40422997&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;대부분의 프로그래밍 언어는 backreference, look-around 같은 확장 기능을 지원하기 위해 백트래킹 NFA를 사용하는데, 이 방식은 최악의 경우 지수 시간이 걸릴 수 있다. 반면 Thompson NFA는 이런 확장 기능을 지원하지 못하지만, 최악의 경우에도 O(mn) 시간을 보장한다. &lt;code&gt;awk&lt;&#x2F;code&gt;, &lt;code&gt;grep&lt;&#x2F;code&gt; 같은 전통적인 Unix 텍스트 처리 도구가 이 방식을 사용한다.&lt;&#x2F;p&gt;
&lt;p&gt;정규표현식이 유한 상태 기계(Finite State Machine)로 구현된다는 사실은 들어봤는데, 실제 코드를 보니 더욱 흥미로웠다. 정규표현식과 FSM을 변환해주는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ivanzuzak.info&#x2F;noam&#x2F;webapps&#x2F;fsm2regex&#x2F;&quot;&gt;FSM2Regex&lt;&#x2F;a&gt;를 사용해보면 이해에 도움이 된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-async-rust-hackernews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;why-async-rust&#x2F;&quot;&gt;Why async Rust?&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=37891020&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Rust의 async가 왜 현재의 모습을 가지는지 핵심 기여자가 설명한 글.&lt;&#x2F;p&gt;
&lt;p&gt;글 자체로도 좋지만, 다중 스레드의 생성 원리, 비동기 실행 모델과 Rust의 executor에 대한 궁금증이 생겨서 추가로 찾아보게 된 좋은 계기였다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cs146s-the-modern-software-developer-gongsig-hangugeo-beonyeogbon&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;themodernsoftware.dev&#x2F;&quot;&gt;CS146S: The Modern Software Developer&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kr.themodernsoftware.dev&#x2F;&quot;&gt;공식 한국어 번역본&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Stanford 강의와 공식 한국어 번역본이다. 강의에서 AI 기반 개발을 꽤 자세하게 다루는 것 같다.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.team-attention.com&#x2F;&quot;&gt;번역하는 팀&lt;&#x2F;a&gt;을 봤는데 시니어&#x2F;리더급 엔지니어 분들이다.&lt;&#x2F;p&gt;
&lt;p&gt;AI 기반 번역이고 검수가 되지 않은 듯한 부분에서 누락&#x2F;오역 등의 문제가 있어 원문과 비교하면서 보는 걸 추천한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;use-the-index-luke&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;use-the-index-luke.com&#x2F;&quot;&gt;Use The Index, Luke&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46751826&quot;&gt;&quot;Introduction to PostgreSQL Indexes&quot; 해커뉴스 글&lt;&#x2F;a&gt;의 댓글에서 추천받아 알게 되었다.&lt;&#x2F;p&gt;
&lt;p&gt;목차까지만 보았는데 SQLP 준비할 때 배웠던 내용과 겹치는 부분이 많아서 잘 구성된거 같고, 여러 DBMS를 다루고 있어서 기억해두려고 한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ai-sidae-ripaegteoringeun-deo-isang-nogadaga-anida-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.lemonbase.team&#x2F;ai-%EC%8B%9C%EB%8C%80-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81%EC%9D%80-%EB%8D%94-%EC%9D%B4%EC%83%81-%EB%85%B8%EA%B0%80%EB%8B%A4%EA%B0%80-%EC%95%84%EB%8B%88%EB%8B%A4-24f3cfae20b6&quot;&gt;AI 시대, 리팩터링은 더 이상 노가다가 아니다&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26040&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;레거시 컴포넌트들이 코드베이스에 혼재하는 문제를 AI와 Codemod로 해결한 사례를 설명한 글이다. AI를 매우 잘 사용한 좋은 예시가 될 수 있겠다.&lt;&#x2F;p&gt;
&lt;p&gt;이런 자동화 관련된 사례가 많이 보이는데, 이제 AI를 사용해서 대규모, 엣지 케이스가 있는 작업도 자동화가 쉽게 가능해진 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;비슷한 글: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;insight.infograb.net&#x2F;blog&#x2F;2026&#x2F;01&#x2F;28&#x2F;claude-skills-gitlab&#x2F;&quot;&gt;Claude Skills로 GitLab 업그레이드 자동화하기&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dibeoging-maindeuses-dibeogingyi-gotongeul-jeolbaneuro-julyeojuneun-gosudeulyi-haengdongpaeteon-ddarahagi&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stdy.blog&#x2F;infcon-2024-debugging-mindset&#x2F;&quot;&gt;디버깅 마인드셋: 디버깅의 고통을 절반으로 줄여주는 고수들의 행동패턴 따라하기&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;실력 있는 개발자들의 디버깅 패턴을 정리한 글. 핵심은 원인 파악에 시간을 투자하고, 정상 동작에 대한 심적 표상(머릿속에 구축된 지식 구조)를 쌓아야 한다는 말.&lt;&#x2F;p&gt;
&lt;p&gt;이전에 읽고 실천했을 때 효과가 좋았고, 오랜만에 봐도 좋은 내용이라고 생각한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;moltbot-jejagja-naneun-ilgji-anheun-kodeureul-baepohanda-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26222&quot;&gt;MoltBot 제작자: “나는 읽지 않은 코드를 배포한다” | GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;창업자 출신인 Peter Steinberger의 개인 프로젝트지만 많은 관심을 받고 있는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.molt.bot&#x2F;&quot;&gt;Moltbot&lt;&#x2F;a&gt;은 메신저를 인터페이스로,
로컬 머신을 실행 환경으로 사용하는 LLM 에이전트 게이트웨이다.
로컬에서 지속적으로 실행되며 개인용 AI 에이전트로 활용할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;개발 워크플로우를 다룬 인터뮤가 공개되었는데, AI 에이전트를 적극 활용한 개발 방식을 사용한다.
코드 자체보다 프롬프트를 보고 결과물을 평가하는 접근이 인상적이였다.&lt;&#x2F;p&gt;
&lt;p&gt;물론 책임 소재가 사용자에게 있는 오픈소스에 개인 프로젝트라서나 가능한 방식이고,
회사 환경에서는 책임 소재나 검증 문제로 그대로 적용하기 어려울 거 같다.&lt;&#x2F;p&gt;
&lt;p&gt;에이전트 기반 개발의 한 방향성으로 참고할 만하다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;seonggonghaneun-eoneoyi-jogeon-creul-gyesog-baeweoya-haneun-iyue-daehan-yigyeon&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sijun-yang.com&#x2F;blog&#x2F;monthly-log-2026-01&#x2F;(https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;Zig&#x2F;comments&#x2F;1fe9f1a&#x2F;comment&#x2F;neblpba&#x2F;)&quot;&gt;성공하는 언어의 조건, C를 계속 배워야 하는 이유에 대한 의견&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;간단한 토이프로젝트를 만드려고 했는데 애플이 제공하는 C 라이브러리를 사용해야 했다. Rust는 FFI가 필요해서, C 라이브러리를 바로 쓸 수 있는 Zig로 해볼까 검색하며 찾아보는 흥미로운 의견을 발견헀다.&lt;&#x2F;p&gt;
&lt;p&gt;Zig는 성공하는 언어의 기준에 맞지 않아 성공하기 어렵고 C는 여전히 필요하다는 흥미로운 의견을 발견했다.
극단적이긴 하지만, 언어가 기업의 선택을 받고 성공하는 기준에 대해 그럴듯하고 공감가는 의견이라 기록해둔다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;geu-oe-sujibhan-geul&quot;&gt;그 외 수집한 글&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.g15e.com&#x2F;pages&#x2F;Source%20code%20quality%20in%20the%20AI%20era&quot;&gt;&lt;strong&gt;AI 시대의 소스코드 품질 - akwiki&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: AI로 작업하면서 품질 하락을 막기 위한 구체적인 도구들을 소개한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;evan-moon.github.io&#x2F;2026&#x2F;01&#x2F;25&#x2F;types-as-proofs-typescript-hidden-math&#x2F;&quot;&gt;&lt;strong&gt;타입 시스템은 왜 증명처럼 동작하는가&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: 예전에 OCmal 공부할 때 Hindley-Milner, Curry-Howard 같은 타입 이론을 들어봤는데, TypeScript를 이런 Curry-Howard 이론 관점에서 설명한다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;n0whur&#x2F;against_curry_howard_mysticism&quot;&gt;언어를 Curry-Howard 이론으로 설명하는게 무용하다는 의견&lt;&#x2F;a&gt;도 있다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;&quot;&gt;&lt;strong&gt;Sylvain Kerkour의 블로그&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: Rust, 보안에 대한 내용을 다룬다. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;rust-devcontainers&quot;&gt;Dev Containers&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;rust-organize-errors-large-projects&quot;&gt;오류 처리&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;rust-web-services-axum-sqlx-postgresql&quot;&gt;Rust, Axum, SQLx 스택&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;rust-how-to-organize-large-workspaces&quot;&gt;대규모 코드베이스 권장사항&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;rust-web-application-clean-architecture&quot;&gt;아키텍처&lt;&#x2F;a&gt; 등을 다룬다. 다만 웹 개발&#x2F;보안 쪽에 치우쳐져 있고 동의하지 않는 주장도 있어 주의하기.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;sigan-deiteoreul-olbareuge-daruneun-bangbeob-beulrogeu-jagseong&quot;&gt;&lt;a href=&quot;&#x2F;blog&#x2F;how-to-handle-time-data&quot;&gt;&quot;시간 데이터를 올바르게 다루는 방법&quot;&lt;&#x2F;a&gt; 블로그 작성&lt;&#x2F;h3&gt;
&lt;p&gt;원래는 핵심 원칙만 간단히 정리할 생각이었지만, 쓰다 보니 시간 처리의 역사나 참고한 Temporal API까지 추가하는 게 이해하기 좋을 것 같아 내용이 대폭 늘었다.
그 과정에서 글의 완성도를 신경 쓰다 보니 시간이 많이 들었다.&lt;&#x2F;p&gt;
&lt;p&gt;다음에 블로그를 쓸 때는 머릿속으로 구조를 완성해두고 명확히 잡는 편이 좋을 것 같다. 이번 글은 아직 하나의 글로 마무리하기에는 준비가 덜 된 주제여서 많은 시간이 걸렸다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;thompson-nfa-guhyeon-ihaehagi&quot;&gt;Thompson NFA 구현 이해하기&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;swtch.com&#x2F;~rsc&#x2F;regexp&#x2F;regexp1.html&quot;&gt;Regular Expression Matching Can Be Simple And Fast&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rosettalens.com&#x2F;s&#x2F;ko&#x2F;regular-expression-matching-can-be-simple-and-fast&quot;&gt;한국어 번역&lt;&#x2F;a&gt;) 글을 보고 Python 코드로 바꿔가며 이해를 높이려고 했다.&lt;&#x2F;p&gt;
&lt;p&gt;정리한 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;426c651856dae8d57ce7907d90429c7d&quot;&gt;Gist 글&lt;&#x2F;a&gt;. AI를 쓰기도 했고, 실제로 여러 번 따라 쳐본 건 아니라 확실하게 이해했다고 하기엔 무리지만, 일단 이 정도면 충분한 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;정규표현식이 어떻게 오토마타로 구현되는지, 백트래킹 방식과 Thompson 알고리즘의 차이가 무엇인지 코드를 통해 이해할 수 있었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-missing-semester-of-your-cs-education-gangyi-hagseub&quot;&gt;The Missing Semester of Your CS Education 강의 학습&lt;&#x2F;h3&gt;
&lt;p&gt;위에서 소개한 MIT 강의를 2020년 버전 위주로 영상과 스크립트를 훑어보았다. 깊이는 얕지만 무엇을 공부해야 할지 폭넓게 다뤄서 좋았다.
모르는 내용도 꽤 있었고, 2026년 강의에서 AI 관련 내용이 추가되는 것 같아 그것도 나중에 볼 예정이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;c78182fd3ff0996ba34de41321c08ae0&quot;&gt;강의 노트&lt;&#x2F;a&gt;는 메모하고 AI로 내용 요약한 정도라 기억에 오래 남진 않을 것 같다.
필요할 때 찾아보는 정도로 쓸 듯.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;airo-tamsaeg-bidonggi-modelgwa-memori-gujo-jeongri&quot;&gt;AI로 탐색: 비동기 모델과 메모리 구조 정리&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;without.boats&#x2F;blog&#x2F;why-async-rust&#x2F;&quot;&gt;&quot;Why async Rust?&quot;&lt;&#x2F;a&gt;를 읽다가 궁금해진 부분을 파고들다 보니 비동기나 스레드의 메모리 위치에 대한 사실들을 알게 되었다.
Gist에 정리하였다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;973e406e46f0f7520ed883bb3b03aa0e&quot;&gt;Rust 비동기 실행 모델의 내부 원리&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;29d81bea78ab4c09a75027fd380f9cb6&quot;&gt;Linux 스레드와 메모리 구조&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;2f2ff6161078a7bfec57d95a689cb06a&quot;&gt;Stackful 비동기의 동작 방식 &amp;amp; 비동기 실행 모델의 분류&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;db-hubreul-sayonghan-mcp-server-sayong&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dbhub.ai&#x2F;&quot;&gt;DB Hub&lt;&#x2F;a&gt;를 사용한 MCP Server 사용&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;추가 — 2026&#x2F;02&#x2F;03&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openai.com&#x2F;index&#x2F;introducing-the-codex-app&#x2F;&quot;&gt;어제(02&#x2F;02) OpenAI가 Mac용 Codex App을 출시했다.&lt;&#x2F;a&gt;
이를 활용하면 별도 채팅 UI를 구축할 필요가 없고, 인증&#x2F;설정에 필요한 env 기반 Bearer token과 Headers를 지원하므로 OAuth Provider 서버를 구축할 필요도 없어졌다.
key-value 기반의 액세스 키만 발급&#x2F;관리 기능만 만들면 가볍게 사용하기 충분하다.
가이드 문서를 제공하여 비개발 직군도 손쉽게 DB 분석 환경을 사용할 수 있게 되었다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;추가 — 2026&#x2F;02&#x2F;12&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;최근에 MCP 서버를 공부하다가 알게 되었는데, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;agents&#x2F;guides&#x2F;remote-mcp-server&#x2F;&quot;&gt;OAuth Provider를 Auth0 같은 별도 서비스를 통해 직접 만들지 않고, mcp-auth-proxy와 같은 프록시를 사용하면 Github이나 Google 같은 외부 Provider를 사용해도 된다.&lt;&#x2F;a&gt;
Google 기반을 사용하면 조직 도메인 등으로 검증할 수 있어 세세한 권한 제어가 필요없는 작은 규모의 조직에서는 좋아보인다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;회사에서 비개발 직군도 회사 DB에 접근할 수 있게 하는 것이 목적이었는데, 관리 비용과 보안 문제로 실패했다. 결국 몇몇 분에게만 VSCode + Codex 환경을 임시로 세팅해 드렸다.&lt;&#x2F;p&gt;
&lt;p&gt;대신 개발 쪽에서 아주 유용하게 쓰고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;팁: 레거시로 인해 스키마&#x2F;컬럼명이 명확하지 않다면, Comment를 함께 전달하도록 tool을 작성하면 AI가 컨텍스트를 더 정확히 파악한다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;문제 배경: 회사 DB 접근 MCP 서버를 비개발자도 안전하게 사용하게 하려면?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MCP 연동 방식별 특성:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 로컬 개발 도구 (Codex, Claude Code 등): 로컬에서 직접 MCP 서버 호출 → IP 화이트리스트 적용 가능&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 로컬 데스크톱 앱 (Claude 앱 등): 외부 MCP 서버 연결 기능 미지원&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  - 웹 서비스 (GPT, Claude 웹): AI 회사 서버 경유 → 우리 측 IP 제한 불가&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;선택지:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. 외부 IP 노출 안 함&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ├─ a. 로컬 개발 도구 사용 (Codex, Claude Code 등)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │      → 문제: 비개발자 사용 어려움, UX 목적과 불일치&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   └─ b. 자체 중간 서버 구축 (LLM API + MCP 연동)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          → 문제: 별도 개발&#x2F;운영 필요&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  별도 채팅 UI&#x2F;서버 필요 (슬랙 연동 등으로 UI 대체가 가능하나 자유로운 대화가 제한)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  API Key 비용 발생&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          → 장점: IP 화이트리스트 유지 가능&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. 외부 IP 노출함&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ├─ a. OAuth Provider 서버 구축 → 자체 인증&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │      → 배경: 웹 환경의 Claude&#x2F;GPT MCP 커넥터는 OAuth 인증 외에 다른 인증은 지원하지 않음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │      → 문제: OAuth Provider 인프라 개발 필요&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │      → 장점: GPT&#x2F;Claude 웹에서 바로 사용, UX 최적, 사용자 관리 가능(IP보다 세밀한 제어 가능)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   └─ b. 퍼블릭 개방&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          → 제외 (보안 불가)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;airo-inhan-hagseubgwa-seongjang-banghyangseonge-daehan-saenggag&quot;&gt;AI로 인한 학습과 성장 방향성에 대한 생각&lt;&#x2F;h3&gt;
&lt;p&gt;요즘 해커뉴스나 긱뉴스를 보면 AI와 개발자 커리어에 대한 글이 자주 올라온다.&lt;&#x2F;p&gt;
&lt;p&gt;극단적인 의견도 있지만, 대부분의 의견은 이렇다. AI로 인한 변화는 피할 수 없고, 시니어급 개발자들이 보기에도 기존 개발 작업 대다수를 대신할 수 있을 정도로 발전했다.&lt;&#x2F;p&gt;
&lt;p&gt;관련한 의견들을 보면서 정리한 생각은, 앞으로 주니어가 성장해야 할 방향에는 크게 3가지 능력이 필요하고 이를 키우기 위해 노력해야 한다는 것이다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;올바른 의사결정을 위한 CS 및 기초 지식
&lt;ul&gt;
&lt;li&gt;기초 지식은 개발뿐 아니라 도메인도 해당될 수 있다. 다만 주니어에게 도메인까지 기대하긴 어렵다.&lt;&#x2F;li&gt;
&lt;li&gt;프레임워크 기반 개발을 하던 과거에도 기초 지식은 중요했다. AI 시대가 되어도 이건 바뀌지 않는다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;AI 활용과 도구 선택 능력
&lt;ul&gt;
&lt;li&gt;AI를 적절한 영역에 사용하고, 자동화&#x2F;프롬프팅&#x2F;에이전트 활용을 통해 효과적으로 동작하게 하는 능력이 중요하다.&lt;&#x2F;li&gt;
&lt;li&gt;동시에 AI가 잘 못하는 부분은 다른 도구로 보완할 수 있어야 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;넓은 범위의 학습&#x2F;적용 능력
&lt;ul&gt;
&lt;li&gt;T자 인재의 필요성은 여전하다. 과거에는 신입에게 하나를 제대로 하거나 기초만 있어도 충분했다.&lt;&#x2F;li&gt;
&lt;li&gt;그러나 AI로 인해 다른 영역으로 확장하기 쉬워졌으므로, 주니어도 그 능력을 키워야 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;관련되서 이번 달에 보았던 글을 정리해두었다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;notes.eatonphil.com&#x2F;2026-01-19-llms-and-your-career.html&quot;&gt;LLMs and your career&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26005&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;karpathy&#x2F;status&#x2F;2015883857489522876&quot;&gt;Andrej Karpathy(OpenAI 공동 창립자)의 Claude 코딩 경험&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=26183&quot;&gt;GeekNews&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46771564&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;antirez.com&#x2F;news&#x2F;158&quot;&gt;Don&#x27;t fall into the anti-AI hype - antirez(Redis 창시자)&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46574276&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;addyosmani.com&#x2F;blog&#x2F;next-two-years&#x2F;&quot;&gt;The Next Two Years of Software Engineering&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=25769&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stdy.blog&#x2F;xp-tdd-and-vibe-coding-kent-beck-interview-with-programmatic-engineer&#x2F;&quot;&gt;XP, TDD, 그리고 바이브 코딩: Kent Beck(TDD&#x2F;XP 창시자)의 인터뷰 번역&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jjalbeun-saenggag&quot;&gt;짧은 생각&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;근황과 요즘 하는 생각&lt;&#x2F;p&gt;
&lt;p&gt;요즘에 AI 활용을 더 적극적으로 시도해보려고 하고 있다.
세계 상위권 대학들이 AI 관련 내용을 커리큘럼에 빠르게 추가하는 걸 보면, 교육 현장에서도 이런 능력이 중요하다고 판단하는 것 같다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>시간 데이터를 올바르게 다루는 방법</title>
          <pubDate>Mon, 12 Jan 2026 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/how-to-handle-time-data/</link>
          <guid>https://sijun-yang.com/blog/how-to-handle-time-data/</guid>
          <description xml:base="https://sijun-yang.com/blog/how-to-handle-time-data/">&lt;p&gt;프로그래밍을 어느 정도 해봤다면, 시간 관련 버그를 한 번쯤은 겪거나 들어보았을 것이다.
서버 환경을 바꾸니 시간이 9시간 밀린다거나, 로컬에서는 잘 되던 게 배포만 하면 시간이 이상하게 보인다거나.&lt;&#x2F;p&gt;
&lt;p&gt;이런 버그가 종종 보이는 이유는 단순한 문자열&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;이나 정수형 타입과 다르게 시간 데이터의 다루는 데 생각보다 많은 주의사항이 존재하기 때문이다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;이 글에서는 시간 데이터의 두 가지 타입과 관련 문제들을 살펴본 뒤, 내가 사용하는 두 가지 원칙을 소개한다.
마지막으로 이 원칙에 영향을 준 JavaScript Temporal API를 간단히 다룬다.&lt;&#x2F;p&gt;
&lt;p&gt;익숙한 Java&#x2F;JavaScript 생태계를 중심으로 설명하지만, 모든 언어에 적용 가능하다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;siganyi-2gaji-taib&quot;&gt;시간의 2가지 타입&lt;&#x2F;h2&gt;
&lt;p&gt;시간 데이터는 크게 두 종류로 나눌 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Exact Time(물리적 순간)&lt;&#x2F;strong&gt;: 유일한 하나의 시점을 가리킨다.
&quot;2024-01-01T00:00:00+00:00&quot;는 전 세계 어디서든 같은 순간이다.
Unix timestamp나 UTC 오프셋을 포함한 ISO 8601 형식(예: 2024-01-01T00:00:00Z)이 여기에 해당한다.&lt;br &#x2F;&gt;
&lt;strong&gt;Wall-clock Time(벽시계 시간)&lt;&#x2F;strong&gt;: 특정 시점이 아니라 날짜와 시간 값 자체를 의미한다.
&quot;12월 25일&quot;은 뉴욕 시간이나 한국 시간처럼 특정 지역의 시간을 의미하지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript의 Temporal API가 이 개념을 잘 설명해서, 이 글에서도 Temporal의 용어를 차용하여 설명한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sigan-deiteoreul-darul-ddae-juyihaeya-hal-jeom&quot;&gt;시간 데이터를 다룰 때 주의해야 할 점&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;taimjon-jeongbo-sonsil&quot;&gt;타임존 정보 손실&lt;&#x2F;h3&gt;
&lt;p&gt;Java의 &lt;code&gt;LocalDateTime&lt;&#x2F;code&gt;은 &lt;code&gt;Local-&lt;&#x2F;code&gt;로 시작하는 이름에서 유추할 수 있듯이 타임존 정보를 저장하지 않는다.
하지만 &lt;code&gt;LocalDateTime.now()&lt;&#x2F;code&gt;를 호출하면 시스템의 기본 타임존을 사용해서 현재 시각을 가져온다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Python의 &lt;code&gt;datetime.now()&lt;&#x2F;code&gt;나 C#의 &lt;code&gt;DateTime.Now&lt;&#x2F;code&gt;도 비슷하게 절대 시점을 저장하지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;이러한 함수를 보았을 때 타임존 변환이 일어났는지 알기 어렵다. 또한 내부 구현에서 타임존 정보를 유지하지 않는다.
객체 생성하는 도중 타임존을 사용해서 변환은 했지만, 결과 객체에선 어떤 타임존이었는지는 저장하지 않는 것이다.
그래서 이 값을 직렬화하거나 저장하면 어느 지역의 시간인지 알 수 없게 된다.
직렬화할 때 로컬의 시간대 정보를 함께 보내면 되지 않나 싶지만,
&lt;code&gt;now()&lt;&#x2F;code&gt; 호출 시 타임존을 직접 지정하는 것도 가능하기 때문에 선언 시점을 제외하면 어떤 타임존이었는지 알 방법이 없다.&lt;&#x2F;p&gt;
&lt;p&gt;특히 요즘의 서비스에선 아주 많은 &quot;로컬&quot;이 존재할 수 있다.
클라이언트와 서버만 있는 간단한 웹 서비스도 2개의 노드가 존재한다.
MSA 서비스라면 LB, DB, Redis, 모니터링 등 서버만 수십 개가 넘어갈 수도 있다.
이때 타임존 없는 시간 문자열을 주고받으면, 원래 어떤 타임존이었는지 복구할 방법이 없다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;yeoreo-gisulyi-hamjeong&quot;&gt;여러 기술의 함정&lt;&#x2F;h3&gt;
&lt;p&gt;다양한 기술 스택에서 타임존 처리와 관련된 함정들이 존재한다.
직렬화 라이브러리, ORM, DB 등에서 타임존 관련 기본 설정이나 옵션이 직관적이지 않아 의도하지 않은 동작을 유발할 수 있다.
몇가지 예시를 살펴보자.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jackson&quot;&gt;Jackson&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;code&gt;DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;은 기본적으로 true로 설정되어 있는데,
이 옵션이 활성화되어 있으면 &lt;code&gt;ZonedDateTime&lt;&#x2F;code&gt;이나 &lt;code&gt;OffsetDateTime&lt;&#x2F;code&gt;을 역직렬화할 때 원본 타임존을 컨텍스트 타임존(기본값 UTC)으로 변환한다.
이 과정에서 시점 정보는 유지되지만, 원래 타임존 정보를 잃어버린다 (이 옵션은 Jackson 3버전 부터 &lt;code&gt;DateTimeFeature&lt;&#x2F;code&gt; 객체로 이관되었다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ansi-sqlyi-timestamp-with-time-zone&quot;&gt;ANSI SQL의 TIMESTAMP WITH TIME ZONE&lt;&#x2F;h4&gt;
&lt;p&gt;ANSI SQL 표준의 &lt;code&gt;TIMESTAMP WITH TIME ZONE&lt;&#x2F;code&gt; 데이터 타입은 이름과 달리 타임존 정보를 유지해야 한다는 요구사항이 없다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
그래서 Oracle의 경우 타임존 정보를 저장하는 반면, PostgreSQL은 타임존 정보를 저장하지 않는 등 제각각의 구현이 존재한다.&lt;&#x2F;p&gt;
&lt;p&gt;PostgreSQL을 자세하게 설명해보자면,
데이터 타입 &lt;code&gt;timestamp&lt;&#x2F;code&gt;(&lt;code&gt;timestamp without time zone&lt;&#x2F;code&gt;)는 문자열로 Wall-clock Time 정보를 저장한다. 그래서 시간 비교 등의 연산에서 취약하다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Exact Time을 저장하려면 &lt;code&gt;timestamptz&lt;&#x2F;code&gt;(&lt;code&gt;timestamp with time zone&lt;&#x2F;code&gt;)를 사용해야 하는데, UTC로 변환되어 저장되고 타임존 정보는 유지되지 않는다.
또한 조회 시 세션의 타임존에 의존하여 시간 결과를 반환한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jpawa-hibernate&quot;&gt;JPA와 Hibernate&lt;&#x2F;h4&gt;
&lt;p&gt;Hibernate는 6.0 이후부터 &lt;code&gt;LocalDateTime&lt;&#x2F;code&gt;은 &lt;code&gt;TIMESTAMP&lt;&#x2F;code&gt;, &lt;code&gt;Instant&lt;&#x2F;code&gt;는 &lt;code&gt;TIMESTAMP_UTC&lt;&#x2F;code&gt;로 매핑된다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
&lt;code&gt;TIMESTAMP_UTC&lt;&#x2F;code&gt;는 저장 시 값을 UTC로 정규화하지만, &lt;code&gt;TIMESTAMP&lt;&#x2F;code&gt;는 변환 없이 그대로 저장된다.
즉, 두 타입을 Exact Time 표현용과 Wall-clock Time 표현용으로 구분하고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;Hibernate는 &lt;code&gt;LocalDateTime&lt;&#x2F;code&gt;을 DB에 저장할 때 JVM 기본 타임존을 기준으로 &lt;code&gt;java.sql.Timestamp&lt;&#x2F;code&gt;로 변환한 뒤 UTC로 정규화한다.
이 과정에서 원본 타임존 정보가 사라진다.
여러 DB 접근 라이브러리를 함께 사용하는 환경에서는 각 라이브러리의 타임존 설정 차이로 인해 시간 오차가 발생할 수 있다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-9-1&quot;&gt;&lt;a href=&quot;#fn-9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Spring Data 개발자 Jens Schauder 역시 &lt;code&gt;LocalDateTime&lt;&#x2F;code&gt;은 타임라인 상의 특정 순간을 표현할 수 없으므로 &lt;code&gt;Instant&lt;&#x2F;code&gt;를 사용하는 것이 바람직하다고 설명한다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;그럼에도 불구하고 많은 코드에서 여전히 Exact Time 데이터를 &lt;code&gt;LocalDateTime&lt;&#x2F;code&gt;으로 선언해 사용하고 있다
(예: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;team-dodn&#x2F;spring-boot-java-template&#x2F;blob&#x2F;750675f8bb7bc97b644e18576a5b26148ac65e17&#x2F;storage&#x2F;db-core&#x2F;src&#x2F;main&#x2F;java&#x2F;io&#x2F;dodn&#x2F;springboot&#x2F;storage&#x2F;db&#x2F;core&#x2F;BaseEntity.java&quot;&gt;spring-boot-java-template BaseEntity의 createdAt, updatedAt&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sigan-deiteoreul-daruneun-2gaji-weoncig&quot;&gt;시간 데이터를 다루는 2가지 원칙&lt;&#x2F;h2&gt;
&lt;p&gt;나는 시간 데이터를 다룰 때 두 가지 원칙을 기준으로 삼고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;이걸 꼭 따라야 한다는 말은 아니다.
하지만 &quot;모든 노드(클라이언트, 서버, DB, 캐시 등)에서 시간 데이터에 대한 해석이 일관되어야 한다.&quot;는 조건을 만족하려면 이 원칙과 비슷한 결론에 도달할 것이다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;weoncig-1-exact-timegwa-wall-clock-timeeul-myeonghwaghi-gubunhara&quot;&gt;원칙 1: Exact Time과 Wall-clock Time을 명확히 구분하라&lt;&#x2F;h3&gt;
&lt;p&gt;시간 데이터가 특정 시점을 나타내는지, 아니면 단순한 날짜&#x2F;시간 값인지 먼저 판단해야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;로그 타임스탬프, 결제 완료 시각, 이벤트 발생 시각처럼 &quot;언제 일어났는가&quot;가 중요한 데이터는 Exact Time으로 저장한다.
Exact Time이 아니면 정확한 시점을 알 수 없기 때문이다.
&lt;code&gt;LocalDateTime.now()&lt;&#x2F;code&gt;처럼 타임존 정보가 사라지는 방식으로 저장하면, 나중에 원래 시점을 복구할 방법이 없다.&lt;&#x2F;p&gt;
&lt;p&gt;생일, 기념일, 공휴일처럼 특정 시점이라는 개념 자체가 없는 데이터는 Wall-clock Time으로 저장해서 날짜&#x2F;시간 값 자체만 저장한다.
이런 데이터를 Exact Time으로 다루면 오히려 문제가 생길 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;단, 이 기준은 도메인에 따라 달라진다.
산부인과 병원 시스템이라면 출생아의 생일이 출생 시점(Exact Time)으로 관리되어야 할 수 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jeojang-pomaes&quot;&gt;저장 포맷&lt;&#x2F;h4&gt;
&lt;p&gt;각 타입에 적합한 저장 포맷을 사용해야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;Exact Time:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Unix timestamp (밀리초 또는 초 단위 정수)&lt;&#x2F;li&gt;
&lt;li&gt;PostgreSQL의 &lt;code&gt;TIMESTAMPTZ&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;ISO 8601 with offset (예: &lt;code&gt;2024-01-01T00:00:00Z&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Wall-clock Time:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DATE&lt;&#x2F;code&gt; 타입 (예: &lt;code&gt;2024-12-25&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;TIME&lt;&#x2F;code&gt; 타입 (예: &lt;code&gt;14:30:00&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;문자열 (예: &lt;code&gt;&quot;2024-12-25&quot;&lt;&#x2F;code&gt;, &lt;code&gt;&quot;14:30&quot;&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;taib-gaegce-seoneon-sijeom-juyisahang&quot;&gt;타입 객체 선언 시점 주의사항&lt;&#x2F;h4&gt;
&lt;p&gt;대부분의 시간 관련 버그는 코드에서 시간 타입을 생성할 때 발생하므로 주의 깊게 보아야 한다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Exact Time이 필요한 곳에서 &lt;code&gt;LocalDateTime.now()&lt;&#x2F;code&gt;를 쓰고 있지는 않은지 확인한다.
&lt;code&gt;Instant.now()&lt;&#x2F;code&gt; 또는 &lt;code&gt;System.currentTimeMillis()&lt;&#x2F;code&gt;를 사용해야 한다.&lt;&#x2F;li&gt;
&lt;li&gt;Wall-clock Time이 필요한 곳에서 UTC 변환을 하고 있지는 않은지 확인한다.
&lt;code&gt;LocalDate.of(2024, 12, 25)&lt;&#x2F;code&gt;처럼 날짜 값 자체만 저장해야 한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;weoncig-2-exact-timeeun-utcro-jeojanghago-taimjoneun-byeoldo-gwanrihara&quot;&gt;원칙 2: Exact Time은 UTC로 저장하고, 타임존은 별도 관리하라&lt;&#x2F;h3&gt;
&lt;p&gt;Exact Time 데이터는 저장, 직렬화&#x2F;역직렬화, 송수신 등 모든 과정에서 UTC 또는 Unix timestamp로 처리한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;taimjoni-pilyohan-gyeongu&quot;&gt;타임존이 필요한 경우&lt;&#x2F;h4&gt;
&lt;p&gt;비행기 출발 시각, 회의 시간처럼 특정 지역의 시간 표현이 필요한 경우에는 Exact Time과 타임존을 별도 필드로 관리한다.&lt;&#x2F;p&gt;
&lt;p&gt;내부적으로는 UTC(Unix timestamp)로 저장하고, 사용자에게 보여줄 때만 해당 타임존으로 변환한다.&lt;&#x2F;p&gt;
&lt;p&gt;이렇게 하면 시간 비교나 집계 등의 계산이 편리해진다. 저장된 값 자체가 바뀌지 않기 때문이다.
앞서 말했듯 타임존 타입의 지원이 아직 완전하지 않거나 주의해야 하는 시스템이 존재하기 때문에&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-11-1&quot;&gt;&lt;a href=&quot;#fn-11&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;,
모든 곳에서 타임존을 UTC로 고정하거나 타임존 정보가 없는 Exact Time인 Unix timestamp 형태로 관리하는 것이 안전하다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;jeonsong-jeojang-sijeom-juyisahang&quot;&gt;전송&#x2F;저장 시점 주의사항&lt;&#x2F;h4&gt;
&lt;p&gt;DB 저장, API 직렬화 등의 과정에서 정보가 손실되는지 확인해야 한다.
명시적인 포맷이나 타입 계약이 없다면, 동일한 값이라도 시스템마다 다르게 해석될 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;DB 데이터 타입, gRPC 같은 스키마 기반 통신 처럼 포맷(타입) 계약이 존재하면 이를 그대로 따른다.&lt;br &#x2F;&gt;
JSON이나 텍스트 기반 통신처럼 계약이 없거나 범용 포맷이 필요한 경우,
Unix timestamp 또는 UTC 오프셋을 포함한 ISO 8601을 사용한다.&lt;&#x2F;p&gt;
&lt;p&gt;ISO 8601는 가독성이 높고, 대부분의 직렬화 라이브러리에서 기본 지원된다.
Unix timestamp는 숫자 자체가 절대 시각이므로 해석 오류 여지가 없고, 저장 공간도 적다.
다만 자동 변환을 지원하지 않는 환경에서는 추가 처리가 필요하다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;dstwa-jeongcaeg-byeongyeong-daeeung&quot;&gt;DST와 정책 변경 대응&lt;&#x2F;h4&gt;
&lt;p&gt;타임존과 시간대 정보가 포함된 데이터를 다루는 경우, 여러 가지 모호한 상황(Ambiguity)이 발생할 수 있다.
이와 관련된 구체적인 예시는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tc39.es&#x2F;proposal-temporal&#x2F;docs&#x2F;timezone.html&quot;&gt;&quot;Temporal Time Zones and Resolving Ambiguity - Temporal Proposal Documentation&quot;&lt;&#x2F;a&gt;에서 찾을 수 있다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-12-1&quot;&gt;&lt;a href=&quot;#fn-12&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;DST 시작&#x2F;종료 같은 일시적 Offset 이동으로 인해서 동일한 벽시계 시간이 두 번 발생(fall back)하거나 존재하지 않는 시간(spring forward)이 생길 수 있다.&lt;&#x2F;li&gt;
&lt;li&gt;정책 변경으로 TimeZone 정의가 변경되어 기존에 저장된 미래 시점의 값과 새로운 규칙 간 충돌이 발생할 수 있다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;지금 설명중인 2가지 원칙들을 따르면 이러한 문제 대부분을 피할 수 있다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;UTC로 저장하면 DST 영향을 받지 않는다. DST는 특정 타임존의 오프셋이 변경되는 것이지, UTC 자체가 바뀌는 것이 아니기 때문이다.&lt;&#x2F;li&gt;
&lt;li&gt;타임존 ID를 별도 필드로 저장하면 정책 변경 시에도 올바른 현지 시간을 계산할 수 있다. IANA 타임존 데이터베이스가 업데이트되면 새로운 규칙이 자동으로 적용된다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;temporal-api-sogae&quot;&gt;Temporal API 소개&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;yeogsajeog-baegyeong&quot;&gt;역사적 배경&lt;&#x2F;h3&gt;
&lt;p&gt;1996년 Java 1.0에서 &lt;code&gt;java.util.Date&lt;&#x2F;code&gt;가 도입됐다.
이는 많은 문제가 있는 구현이였는데, 월이 0부터 시작하고 연도는 1900을 빼서 저장하고 객체가 mutable해서 언제든 값이 바뀔 수 있었다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-13-1&quot;&gt;&lt;a href=&quot;#fn-13&quot;&gt;13&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript가 만들어질 때, Java의 Date 구현을 거의 그대로 가져왔다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-14-1&quot;&gt;&lt;a href=&quot;#fn-14&quot;&gt;14&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
Java는 이후 개선을 시도한 반면, Date는 거의 30년이 지난 지금까지 사용되고 있다. (그래서 프로덕션 환경에선 별도의 시간 라이브러리를 많이 쓴다.)&lt;&#x2F;p&gt;
&lt;p&gt;2002년 Stephen Colebourne이 Java Date의 문제를 보완한 Joda-Time 라이브러리를 만들었다.
Joda-Time은 큰 성공을 거뒀고, 2014년 Java 8의 공식 &lt;code&gt;java.time&lt;&#x2F;code&gt; 패키지(JSR-310)로 이어졌다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-15-1&quot;&gt;&lt;a href=&quot;#fn-15&quot;&gt;15&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;JavaScript에서는 Date의 문제를 해결하기 위해 Temporal API 제안이 진행되었고,
TC39(ECMAScript 기술위원회)에서 이 제안은 Stage 3(명세가 확정되어 구현을 진행) 상태에 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;temporalyi-seolgye&quot;&gt;Temporal의 설계&lt;&#x2F;h3&gt;
&lt;p&gt;Temporal은 Exact Time과 Wall-clock Time의 구분을 타입 시스템에서 강제한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;temporal-object-model.svg&quot; alt=&quot;Temporal Object Model&quot; &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tc39.es&#x2F;proposal-temporal&#x2F;docs&#x2F;object-model.svg&quot;&gt;원본 링크&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;위 다이어그램에서 왼쪽은 Exact Time(물리적 순간)을 아는 타입들이고, 오른쪽은 Wall-clock Time(벽시계 시간)을 아는 타입들이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Temporal.Instant&lt;&#x2F;code&gt;는 물리적 순간만 표현한다. 타임존이나 캘린더 없이 절대 시점만 저장한다.
&lt;code&gt;Temporal.ZonedDateTime&lt;&#x2F;code&gt;은 물리적 순간에 타임존과 캘린더를 더해서 양쪽에 걸쳐 있다.
반면 &lt;code&gt;Plain-&lt;&#x2F;code&gt; 접두사가 붙은 타입들(&lt;code&gt;PlainDateTime&lt;&#x2F;code&gt;, &lt;code&gt;PlainDate&lt;&#x2F;code&gt;, &lt;code&gt;PlainTime&lt;&#x2F;code&gt; 등)은 타임존 정보가 없다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;temporal-persistence-model.svg&quot; alt=&quot;Temporal Persistence Model&quot; &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tc39.es&#x2F;proposal-temporal&#x2F;docs&#x2F;persistence-model.svg&quot;&gt;원본 링크&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;이 다이어그램은 각 타입이 문자열로 직렬화될 때 어떤 정보가 포함되는지 보여준다.
&lt;code&gt;Instant&lt;&#x2F;code&gt;는 UTC 시간만, &lt;code&gt;ZonedDateTime&lt;&#x2F;code&gt;은 오프셋과 타임존 ID까지, &lt;code&gt;Plain&lt;&#x2F;code&gt; 타입들은 날짜&#x2F;시간 정보만 포함된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;plain-vs-local&quot;&gt;Plain vs Local&lt;&#x2F;h3&gt;
&lt;p&gt;여기서 &quot;Plain&quot;이라는 네이밍이 중요하다. java.time의 &quot;Local&quot;은 이름에서 위치를 암시하지만, &quot;Plain&quot;은 타임존에 대한 어떤 가정도 없다는 것을 명확히 보여준다.
단순하게 날짜와 시간 값 자체만을 표현한다는 의미가 더 직관적으로 드러난다. Temporal의 설계자들 역시 이러한 의도를 가지고 Plain이라는 이름을 선택했다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-16-1&quot;&gt;&lt;a href=&quot;#fn-16&quot;&gt;16&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-17-1&quot;&gt;&lt;a href=&quot;#fn-17&quot;&gt;17&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;temporal-nowyi-bunri&quot;&gt;Temporal.Now의 분리&lt;&#x2F;h3&gt;
&lt;p&gt;Temporal은 &quot;now&quot;를 다루는 방식이 기존의 일반적인 라이브러리와 다르다.
&lt;code&gt;Temporal.Now&lt;&#x2F;code&gt;라는 별도 객체가 존재해서, &lt;code&gt;Temporal.Now.instant()&lt;&#x2F;code&gt;나 &lt;code&gt;Temporal.Now.plainDateTimeISO()&lt;&#x2F;code&gt; 같은 형태로 사용한다.
현재 시각 조회를 별도 API로 분리해서 타임존 정보 손실이 발생할 수 있다는 것을 API 표면에서 명확하게 알려준다.
반면 java.time에서는 &lt;code&gt;LocalDateTime.now()&lt;&#x2F;code&gt;처럼 각 타입에 now 메서드가 붙어 있어 정보 손실이 발생 가능하다는 것이 명확하지 않다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;aemaemohohan-sanghwang-ceori&quot;&gt;애매모호한 상황 처리&lt;&#x2F;h3&gt;
&lt;p&gt;Temporal은 Plain 타입에서 Exact 타입으로 변환할 때 발생하는 모호함을 다루는 방법을 개발자가 선택할 수 있게 한다&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-12-2&quot;&gt;&lt;a href=&quot;#fn-12&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;앞서 제시한 원칙을 따르면 이런 기능이 필요한 상황 자체가 드물어진다.
다만 레거시 데이터 마이그레이션이나 사용자 입력 처리 같은 예외 상황에서는 유용하므로, 어떤 옵션을 제공하는지 알아두면 좋다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;사실 문자열도 그렇게 단순하지는 않다. 유니코드, 인코딩, 정규화 등 고려해야 할 사항이 많다. 이와 관련해서는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tonsky.me&#x2F;blog&#x2F;unicode&#x2F;&quot;&gt;The Absolute Minimum Every Software Developer Must Know About Unicode in 2023&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;utf8everywhere.org&#x2F;#&quot;&gt;UTF-8 Everywhere&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;yozm.wishket.com&#x2F;magazine&#x2F;detail&#x2F;2836&#x2F;&quot;&gt;아�니 이 글자 왜 들어간 거예요?&lt;&#x2F;a&gt; 같은 글을 읽어보는 걸 추천한다. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;여기서 다루는 내용과 별개지만, 시간 데이터의 정확성 자체도 완벽하지 않다. 분산 시스템에서 &quot;정확한 시간&quot;을 정의하는 것 자체가 매우 어려운 문제다. 이와 관련해서는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dataintensive.net&#x2F;&quot;&gt;&quot;Designing Data-Intensive Applications&quot;&lt;&#x2F;a&gt;, Chapter 8: &#x27;Unreliable Clocks&#x27;를 읽어보는 것을 추천한다. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;OpenJDK, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openjdk&#x2F;jdk&#x2F;blob&#x2F;jdk-27%2B3&#x2F;src&#x2F;java.base&#x2F;share&#x2F;classes&#x2F;java&#x2F;time&#x2F;LocalDateTime.java#L213&quot;&gt;&quot;LocalDateTime.java source code&quot;&lt;&#x2F;a&gt;, GitHub. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Jackson, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fasterxml.github.io&#x2F;jackson-databind&#x2F;javadoc&#x2F;2.6&#x2F;com&#x2F;fasterxml&#x2F;jackson&#x2F;databind&#x2F;DeserializationFeature.html&quot;&gt;&quot;DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE&quot;&lt;&#x2F;a&gt;, JavaDoc. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;Jackson 3.0.3, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;javadoc.io&#x2F;doc&#x2F;tools.jackson.core&#x2F;jackson-databind&#x2F;latest&#x2F;tools.jackson.databind&#x2F;tools&#x2F;jackson&#x2F;databind&#x2F;cfg&#x2F;DateTimeFeature.html&quot;&gt;&quot;DateTimeFeature&quot;&lt;&#x2F;a&gt;, JavaDoc. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;SQL-92 Standard, Section 4.5 &quot;Datetimes and intervals&quot; - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;modern-sql.com&#x2F;standard&quot;&gt;Modern SQL&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.contrib.andrew.cmu.edu&#x2F;~shadow&#x2F;sql&#x2F;sql1992.txt&quot;&gt;Full Draft&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;PostgreSQL Wiki, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.postgresql.org&#x2F;wiki&#x2F;Don&amp;#x27;t_Do_This#Don&amp;#x27;t_use_timestamp_(without_time_zone)_to_store_UTC_times&quot;&gt;&quot;Don&#x27;t Do This&quot;&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;Hibernate ORM, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hibernate&#x2F;hibernate-orm&#x2F;blob&#x2F;6.0&#x2F;migration-guide.adoc#instant-mapping-changes&quot;&gt;&quot;Instant mapping changes&quot;&lt;&#x2F;a&gt;, Migration Guide, Version 6.0. &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-9&quot;&gt;
&lt;p&gt;jOOQ GitHub, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jOOQ&#x2F;jOOQ&#x2F;issues&#x2F;11753&quot;&gt;&quot;LocalDateTime param binding handled differently by hibernate&quot;&lt;&#x2F;a&gt;, Issue #11753, 2021. &lt;a href=&quot;#fr-9-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Jens Schauder, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.schauderhaft.de&#x2F;2018&#x2F;03&#x2F;14&#x2F;dont-use-localdatetime&#x2F;&quot;&gt;&quot;Don&#x27;t use LocalDateTime&quot;&lt;&#x2F;a&gt;, Schauderhaft Blog, 2018. &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-11&quot;&gt;
&lt;p&gt;Hibernate ORM Discussion, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hibernate&#x2F;hibernate-orm&#x2F;discussions&#x2F;4201#discussioncomment-1291666&quot;&gt;&quot;Support timestamp with timezone&#x2F;offset&quot;&lt;&#x2F;a&gt;, GitHub. &lt;a href=&quot;#fr-11-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-12&quot;&gt;
&lt;p&gt;TC39, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tc39.es&#x2F;proposal-temporal&#x2F;docs&#x2F;timezone.html&quot;&gt;&quot;Temporal Time Zones and Resolving Ambiguity&quot;&lt;&#x2F;a&gt;, Temporal Proposal Documentation. &lt;a href=&quot;#fr-12-1&quot;&gt;↩&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-12-2&quot;&gt;↩2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-13&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;tutorial&#x2F;datetime&#x2F;iso&#x2F;legacy.html&quot;&gt;&quot;Legacy Date-Time Code&quot;&lt;&#x2F;a&gt;, The Java Tutorials. &lt;a href=&quot;#fr-13-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-14&quot;&gt;
&lt;p&gt;Allen Wirfs-Brock, Brendan Eich, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;10.1145&#x2F;3386327&quot;&gt;&quot;JavaScript: The First 20 Years&quot;&lt;&#x2F;a&gt;, Proceedings of the ACM on Programming Languages, Volume 4, June 2020 (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;js-history.vercel.app&#x2F;&quot;&gt;비공식 한국어 번역&lt;&#x2F;a&gt;). &lt;a href=&quot;#fr-14-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-15&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;8&#x2F;docs&#x2F;technotes&#x2F;guides&#x2F;datetime&#x2F;index.html&quot;&gt;&quot;Java Date Time APIs&quot;&lt;&#x2F;a&gt;, Java Platform, Standard Edition 8; JSR 310 Expert Group, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jcp.org&#x2F;en&#x2F;jsr&#x2F;detail?id=310&quot;&gt;&quot;JSR 310: Date and Time API&quot;&lt;&#x2F;a&gt;, Java Community Process. &lt;a href=&quot;#fr-15-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-16&quot;&gt;
&lt;p&gt;TC39 Temporal Proposal, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tc39&#x2F;proposal-temporal&#x2F;issues&#x2F;707&quot;&gt;&quot;What should be the long-term name of LocalDateTime?&quot;&lt;&#x2F;a&gt;, GitHub Issue #707. &lt;a href=&quot;#fr-16-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-17&quot;&gt;
&lt;p&gt;여러 시간 라이브러리에서 사용되는 &lt;code&gt;Local-&lt;&#x2F;code&gt; 네이밍은 C언어의 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;c&#x2F;chrono&#x2F;localtime.html&quot;&gt;&lt;code&gt;localtime()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; 함수에서 유래했을 것으로 추측한다. 표준처럼 굳어진 용어를 바꾸자는 주장에 마냥 동의하지는 않지만, &lt;code&gt;Local-&lt;&#x2F;code&gt;의 의미가 명확하지 않은 것은 사실이라 이 경우에는 이름을 바꾸는 결정이 합리적이라고 본다. &lt;a href=&quot;#fr-17-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 2025년 12월</title>
          <pubDate>Wed, 31 Dec 2025 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-2025-12/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-2025-12/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-2025-12/">&lt;p&gt;RDB 기반 큐로 회사 내부에 문제 많던 코드를 개선했는데, 만족스러운 경험이였다.
나중에 기회가 되면 다뤄볼까 한다. 또한 새로운 블로그 글도 작성했는데, 이 두 작업에 이번 달의 대부분을 투자했다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;lobsters-haekeonyuseuwa-biseushajiman-codaejero-unyeongdoeneun-keomyuniti-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;&quot;&gt;Lobsters - 해커뉴스와 비슷하지만 초대제로 운영되는 커뮤니티&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=12178&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;기본적으로 해커뉴스를 더 많이 보긴 하는데, 여기에도 재미있거나 유익한 내용이 많다.
업로드 가능한 사람이 제한적이라 그런지 올라오는 글이 해커뉴스와 잘 겹치지 않는 것 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sqliteneun-eoddeohge-teseuteudoeneunga-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sqlite.org&#x2F;testing.html&quot;&gt;SQLite는 어떻게 테스트되는가&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=25168&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;SQLite의 테스트 방법론에 대한 공식 문서이다.&lt;&#x2F;p&gt;
&lt;p&gt;SQLite가 최근 서버 쪽에서도 사용하자는 의견이 종종 보여서 찾아보다가 알게 되었다.
로컬에서 돌려도 될 만큼 가볍고, 생각보다 높은 성능과, 수많은 기기에서 쓰일만큼 높은 신뢰도가 마음에 든다.&lt;&#x2F;p&gt;
&lt;p&gt;토이프로젝트에서 서버를 만들어야 한다면 Rust, SQLite를 사용해 만들어보고 싶다는 생각을 하고 있다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=4558&quot;&gt;SQLite의 알려지지 않은 이야기 | GeekNews&lt;&#x2F;a&gt;나 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sqlite.org&#x2F;qmplan.html&quot;&gt;Quality Management&lt;&#x2F;a&gt;도 함께 보면 좋다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wide-events-rogingyi-saeroun-paereodaim&quot;&gt;Wide Events: 로깅의 새로운 패러다임&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=25239&quot;&gt;Wide Events 소개 | GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;loggingsucks.com&#x2F;&quot;&gt;Logging Sucks - Wide Events 공식 사이트&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46346796&quot;&gt;HackerNews 토론&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;기존 로깅 방식의 근본적인 문제를 해결하려는 새로운 접근법. 요청당 수십 줄의 분산된 로그 대신, 하나의 포괄적인 구조화된 이벤트를 발행하자는 의견이다.&lt;&#x2F;p&gt;
&lt;p&gt;공감하는 사람들도 많을거라 생각하는데, 서비스의 로그를 분석하다 보면 불편한 상황이 많이 생긴다.
필요한 정보를 주는 로깅이 없다거나, 연결된 로그를 찾기 어렵다거나 등등.&lt;&#x2F;p&gt;
&lt;p&gt;실제 운영을 통한 평가를 받아봐야 확실해지겠지만, 이 기법을 사용한다면 문제 해결이 쉬워지지 않을까 싶다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nanali-baljeonhagopeun-gaebaljareul-wihan-ai-hwalyongbeob&quot;&gt;나날이 발전하고픈 개발자를 위한 AI 활용법&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;drive.google.com&#x2F;file&#x2F;d&#x2F;1h99VB5Ra5nn78ZpcXzvN8HyJbSmcX-Qn&#x2F;view&quot;&gt;발표 자료 (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;CAgn60EWDmw?si=IwQRUollHuL11TxA&quot;&gt;유튜브 영상&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;lucas_flatwhite&#x2F;status&#x2F;1962061940815257606&quot;&gt;X&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;관심 가는 거만 메모했다. 빠진부분이 많다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;조언
&lt;ul&gt;
&lt;li&gt;AI는 변화가 빨라서 몇 개월만 지나도 지식이 outdated됨&lt;&#x2F;li&gt;
&lt;li&gt;학습 모드(Study Mode) 등 LLM이 제공하는 새로운 기능들을 시도해봐야 함&lt;&#x2F;li&gt;
&lt;li&gt;여전히 가장 중요한 인사이트(고객, 지식)는 사람으로부터 나온다&lt;&#x2F;li&gt;
&lt;li&gt;AI 관련 무료 공식 자료가 풍부함: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.anthropic.com&#x2F;en&#x2F;docs&#x2F;build-with-claude&#x2F;prompt-engineering&#x2F;overview&quot;&gt;Anthropic Prompt Engineering&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ai.google.dev&#x2F;gemini-api&#x2F;docs&#x2F;prompting-strategies&quot;&gt;Google Prompt Engineering&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;platform.openai.com&#x2F;docs&#x2F;guides&#x2F;prompt-engineering&quot;&gt;OpenAI Prompt Engineering Guide&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;anthropics&#x2F;courses&quot;&gt;Anthropic Courses&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.deeplearning.ai&#x2F;&quot;&gt;deeplearning.ai&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;(메모: 요즘엔 Vercel의 React 프롬프트, Supabase의 PostgreSQL 프롬프트 같이 프롬프트 공유도 많이 하는 듯)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;코딩 관점
&lt;ul&gt;
&lt;li&gt;What + Why를 효과적으로 주는 프롬프팅: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;spilist.notion.site&#x2F;R-STICC-ce9f791017f34f57bfb0a870f2601b57&quot;&gt;STICC&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;여전히 일부 분야에서 How가 필요: CTA(Cognitive Task Analysis, 인지 작업 분석)필요. AI와 반복적인 학습을 통한 이해. AI가 메타 평가.&lt;&#x2F;li&gt;
&lt;li&gt;MCP는 다양한 기능이 있지만 대부분 툴 기능만 사용됨, 켰다 껐다 가능하므로 필요할때만 써서 토큰 아끼기&lt;&#x2F;li&gt;
&lt;li&gt;정적 타입 검사, 린터 등 Validator 활용하기, AI보다 정확함: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.g15e.com&#x2F;pages&#x2F;Source%20code%20quality%20in%20the%20AI%20era&quot;&gt;AI 시대의 소스코드 품질&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stdy.blog&#x2F;tag&#x2F;meeting-debugging-experts-kr&#x2F;&quot;&gt;디버깅 마인드셋&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stdy.blog&#x2F;infcon-2024-debugging-mindset&#x2F;&quot;&gt;인프콘 2014 발표&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Kent Beck의 TDD와 AI 관련 내용: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stdy.blog&#x2F;xp-tdd-and-vibe-coding-kent-beck-interview-with-programmatic-engineer&#x2F;&quot;&gt;XP, TDD, 그리고 바이브 코딩: Kent Beck의 Programmatic Engineer 인터뷰 일부 번역&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;제품 개발 관점
&lt;ul&gt;
&lt;li&gt;문제 정의(누구를 위해, 왜, 무엇을)에서부터 시작함&lt;&#x2F;li&gt;
&lt;li&gt;LLM&#x2F;에이전트가 항상 정답은 아님: 비용을 지불하는 건 문제 해결이지 AI 자체가 아님&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brunch.co.kr&#x2F;@shndon0220&#x2F;153&quot;&gt;미국 VC가 언급한 지금 AI로 창업하기 어려운 분야들&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;MVP, MMP, MLP 개념과 올바른 이해: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;startups&#x2F;comments&#x2F;eber4l&#x2F;your_guide_to_mvp_mmp_mlp_mdp_and_map_startup&#x2F;?tl=ko&quot;&gt;MVP, MMP, MLP, MDP, MAP 스타트업 단계 가이드 : r&#x2F;startups&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.fixate.it&#x2F;blog&#x2F;minimum-viable-product-minimum-marketable-product-or-minimum-loveable-product-whats-best&quot;&gt;MVP, MMP or MLP. What&#x27;s best?&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;feed&#x2F;update&#x2F;urn:li:activity:7350330223319535620&#x2F;&quot;&gt;MVP에 대한 정확한 해석에 대한 의견&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;geu-oe&quot;&gt;그 외&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ratsplaydoom.com&#x2F;&quot;&gt;시궁쥐(Rat)에게 DOOM 학습시키기&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: 그냥 순수하게 재미있는 프로젝트. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;yolorun_capital&#x2F;status&#x2F;1996632980903620886?s=20&quot;&gt;지금도 진행중인 듯&lt;&#x2F;a&gt;하다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;containersonaws.com&#x2F;pattern&#x2F;nginx-reverse-proxy-sidecar-ecs-fargate-task&#x2F;&quot;&gt;AWS ECS의 리버스 프록시 사이드카 패턴 | Containers on AWS&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: AWS 직원들이 운영중인 비공식 블로그의 글. 가끔 보이는 패턴인데 명확한 이유를 찾기 어려워 궁금했던 내용. 주요 이점은 작업 분담(압축), 효율적인 트래픽 처리이다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=2758&quot;&gt;오픈 소스 어플리케이션의 아키텍쳐 | GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: 인사이트 출판사에서 1권 번역본을 샀었는데, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aosabook.org&#x2F;en&#x2F;index.html&quot;&gt;원서&lt;&#x2F;a&gt;는 무료로 공개되어 있다. 많은 오픈소스 프로젝트의 핵심 기여자들이 프로젝트의 설계 철학을 말해준다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1pn6010&#x2F;compio_instead_of_tokio_what_are_the_implications&#x2F;&quot;&gt;Tokio와 Compio의 차이 - 비동기 모델 비교 | Reddit&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: epoll vs io_uring 기반 비동기 런타임의 차이점. IGGY의 주요 개발자가 답글을 달았는데 쉽게 설명해준다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=25130&quot;&gt;&lt;strong&gt;&lt;br&gt; 태그로 돌아본 웹의 30년 | GeekNews&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;: 웹 생태계의 진화 과정을 다룬 글. 프론트엔드뿐 아니라 백엔드 개발자도 알면 유익한 내용.  관련 글: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=21170&quot;&gt;JavaScript의 간략한 역사 | GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;rdb-giban-kyureul-sayonghaebogi&quot;&gt;RDB 기반 큐를 사용해보기&lt;&#x2F;h3&gt;
&lt;p&gt;DB의 작업 성공과 함께 사이드이펙트나 추가 처리(알림, 비동기 처리)가 필요한 경우, MQ가 유용하다.
하지만 당장 고트래픽 처리와 확장성이 필요 없다면 DB 기반 스케줄러를 쓰는 게 더 좋다. (90% 이상의 경우 여기에 해당할 것이다.)&lt;&#x2F;p&gt;
&lt;p&gt;회사에서 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kagkarlsson&#x2F;db-scheduler&quot;&gt;db-scheduler&lt;&#x2F;a&gt;를 사용하여 별도 인프라 추가 없이 단계별로 복구 가능한 Task를 만들 수 있었고,
기존의 여러 문제를 해결하는 만족스러운 결과를 얻었다. 이에 대한 건 따로 블로그를 써볼 예정이다.&lt;&#x2F;p&gt;
&lt;p&gt;우아한형제들 기술블로그에서도 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;techblog.woowahan.com&#x2F;23625&#x2F;&quot;&gt;유사한 패턴을 직접 구현한 사례&lt;&#x2F;a&gt;가 있다. (왜 직접 만들었는지는 모르겠지만)&lt;&#x2F;p&gt;
&lt;p&gt;Rust에는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apalis-dev&#x2F;apalis&quot;&gt;apalis&lt;&#x2F;a&gt;가 제일 유명한 거 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;beulrogeu-geul-donggi-bidonggi-beulroking-nonbeulroking-gaenyeomeun-eodiseobuteo-jalmosdoeeossna-jagseong&quot;&gt;블로그 글 &quot;&lt;a href=&quot;&#x2F;blog&#x2F;blocking-nonblocking-sync-async-misconceptions&#x2F;&quot;&gt;동기&#x2F;비동기, 블로킹&#x2F;논블로킹 개념은 어디서부터 잘못되었나&lt;&#x2F;a&gt;&quot; 작성&lt;&#x2F;h3&gt;
&lt;p&gt;X에서 개발 관련 포스팅을 보면서 시간을 때우곤 하는데, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;finalchildmc&#x2F;status&#x2F;1654007292772376581?s=20&quot;&gt;동기&#x2F;비동기 관련 사분면이 잘못되었다는 글&lt;&#x2F;a&gt;을 보게 되었다.&lt;&#x2F;p&gt;
&lt;p&gt;명확하게 설명은 못했지만 저런 사분면으로 나눠서 설명하는 것이 뭔가 이상하다는 생각을 가지고 있던 터라,
AI를 활용해 여러 자료를 찾아보았다. 이런 사분면 설명은 잘못된 설명이라는 걸 알게 되어 글을 작성했다.&lt;&#x2F;p&gt;
&lt;p&gt;요즘엔 AI를 사용하면 이전에 비해 자료 검색 속도가 말도 안 되게 빨라졌다. 정확한 자료를 빠르게 찾아볼 수 있어서 좋다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jjalbeun-saenggag&quot;&gt;짧은 생각&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;근황과 요즘하는 생각&lt;&#x2F;p&gt;
&lt;p&gt;기존에 오픈소스 기여에 관심을 가지고 더 깊이 있는 부분에 참여하고 싶었지만, 아직 많이 부족함을 느끼고 있다.
기초적인 능력 향상에 집중하기 위해 한동안은 쉴 예정이다.&lt;&#x2F;p&gt;
&lt;p&gt;AI를 개발과 자료조사에 적극 활용하면서, 공식문서나 개념을 쉽게 풀어쓴 블로그 글을 볼 필요가 없어졌다.
이제는 전문성 있는 글이나 개인적인 시선이 담긴 글 위주로 보고, 나도 그런 글을 쓰려고 하고 있다. (어떻게 보면 AI가 저품질 글을 대체했다고 볼 수 있을까?)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 이전 자료 모음</title>
          <pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-before/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-before/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-before/">&lt;p&gt;월간 기록을 시작했는데, 이전에 정리한 자료 중에서도 좋은게 많다.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;월간 기록&quot;이라고 볼 순 없지만 버리기는 아까워, 최근 몇 개월 동안 모아두었던 기록 중에 다시 찾아볼 만한 것들을 정리했다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sujib&quot;&gt;수집&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;흥미롭거나 유용했던 자료들&lt;&#x2F;p&gt;&lt;h3 id=&quot;computer-networks-a-systems-approach-muryo-weonseo&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;book.systemsapproach.org&#x2F;index.html&quot;&gt;Computer Networks: A Systems Approach (무료 원서)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;나는 한글 번역본을 책으로 가지고 있는데, 영어 원서는 무료로 공개되어 있다. 네트워크를 제대로 공부하고 싶을 때 참고하면 좋을 듯.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interactive-sicp-js&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sourceacademy.org&#x2F;sicpjs&#x2F;index&quot;&gt;Interactive SICP JS&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;SICP의 설명을 Scheme 대신 기능이 제한된 JS로 대체한 에디션이다. 인터넷에서 무료로 볼 수 있고 실행 환경을 구축할 필요 없이 웹사이트에서 실습할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;원문 또한 검색하면 공식적으로 무료로 풀려있고, 원문과 SICP in JS의 내용을 비교하고 싶다면 여기의 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sicp.sourceacademy.org&#x2F;#&quot;&gt;비교판&lt;&#x2F;a&gt;에서 볼 수 있다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;SICP(Structure and Interpretation of Computer Programs, 컴퓨터 프로그램의 구조와 해석)는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wisdomandwonder.com&#x2F;link&#x2F;2110&#x2F;why-mit-switched-from-scheme-to-python&quot;&gt;전 MIT 입문 프로그래밍 교재&lt;&#x2F;a&gt;로, Scheme(Lisp 방언)을 사용해 추상화, 재귀, 데이터 구조, 인터프리터&#x2F;컴파일러 구현 등 컴퓨팅의 본질적 개념을 다룬다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;나는 특히 3장에서 substitution model에서 environment model로 전환하는 것과 4장에서 겉보기에는 동일한 언어라도 평가 전략이나 실행 모델과 같은 구현 선택에 따라 동작이 달라질 수 있다는 점이 인상 깊었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cloudflare-hangugeseoyi-mang-yeondong-munje&quot;&gt;Cloudflare 한국에서의 망 연동 문제&lt;&#x2F;h3&gt;
&lt;p&gt;Cloudflare는 망 사용료로 인한 비용 문제로 CDN 사용 시 국외의 노드와 연결된다.
한국에 ICN(인천) 리전이 있지만, Enterprise 플랜을 사용해야만 고정이 가능하다.&lt;&#x2F;p&gt;
&lt;p&gt;CDN 뿐만 아니라 R2나 다른 기능들에서도 한국 리전이 사용되지 않는 듯 하나 확실하진 않다.&lt;&#x2F;p&gt;
&lt;p&gt;이에 대한 공식적인 내용을 찾아보기는 어렵지만, 사실 상 망 사용료로 인한 문제임이 확실한 것 같다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gameple.co.kr&#x2F;news&#x2F;articleView.html?idxno=208925&quot;&gt;클라우드플레어 임원 &quot;한국 망 사용료가 비슷하다고? 20배 이상 비싸&quot;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;marinesnow34.github.io&#x2F;2023&#x2F;09&#x2F;23&#x2F;s3r2&#x2F;&quot;&gt;관련 블로그 글&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;namu.wiki&#x2F;w&#x2F;Cloudflare#s-4&quot;&gt;나무위키&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gaonwiki.com&#x2F;a&#x2F;s5J&quot;&gt;가온위키(처음 보는 위키인데 내용이 많아서 링크)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;sqlgwa-gwangyehyeong-model&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kihyo-park.github.io&#x2F;blog&#x2F;rdb-intro&#x2F;&quot;&gt;SQL과 관계형 모델&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;관계형 모델의 이론과 RDB를 연관지어 설명한다.&lt;&#x2F;p&gt;
&lt;p&gt;실제 DM 사용 경험이 적다곤 하지만, 이런 관점의 글은 본 적 없고 인상깊었다.&lt;&#x2F;p&gt;
&lt;p&gt;아마 블로그 글 저자가 컴파일러나 언어학에 관심이 있어서 이런 관점의 글이 나온거 같음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tempeulris-kolbaeg-paeteongwa-seupeuring-teuraenjaegsyeon-gwanri-bangbeob&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;84f6b453b6687491a2b1756498f5ed5f&quot;&gt;템플릿 콜백 패턴과 스프링 트랜잭션 관리 방법&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;고등학교 후배의 포트폴리오 프로젝트 코드를 보다가 궁금해져서 찾아본 내용.
라이브러리 사용자가 Context를 알지 않아도 실행 가능하게 하는 편리한 패턴이라고 생각된다.&lt;&#x2F;p&gt;
&lt;p&gt;전역이 아닌 별도의 생명 주기를 가지는 Context는 어떤 식으로 관리되는지 생각해볼 수 있었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5jjari-peurompeuteuro-2-418jjari-cwiyagjeom-cajeun-sseol-geeknews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;new-blog.ch4n3.kr&#x2F;llm-found-security-issues-from-django-ko&#x2F;&quot;&gt;$5짜리 프롬프트로 $2,418짜리 취약점 찾은 썰&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=24828&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;내용이 좋다. 실제로 LLM을 사용한 긍정적이고 효과적인 방법이라고 볼 수 있을 듯. 오픈소스 기여나 학습 측면에서 이런 시도가 나오고 있다는건 좋은 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;하지만 이와 반대로 LLM이 오픈소스 생태계 유지에 악영향을 줄 수 있을 것 같아 걱정이다.
FFmpeg, cURL, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;posts&#x2F;snicoll_goodbye-albon-idrizi-httpslnkdin-activity-7405253562458378240-Jxu9&#x2F;&quot;&gt;Spring&lt;&#x2F;a&gt; 같은 여러 오픈소스에서도 AI Slop이 많아져 불만을 표하는 글을 보기도 했고.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sqlite-cangsijaga-jeanhan-crlf-geuman-bonaegi-seoneon-geurigo-ceolhoe-hackernews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fossil-scm.org&#x2F;home&#x2F;ext&#x2F;stop-requiring-crlf.md&quot;&gt;SQLite 창시자가 제안한 &quot;CRLF 그만 보내기&quot; 선언 (그리고 철회)&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=41830717&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;이런 역사적 잔재는 생각보다 많다. tty, base64 등. 지금 당연하게 쓰는 관행이 사실은 수십 년 전 하드웨어 제약의 흔적인 경우가 많다.&lt;&#x2F;p&gt;
&lt;p&gt;SQLite 창시자 Richard Hipp이 &quot;이제 CR은 그만 보내자&quot;는 선언문을 작성했다가 철회했다. 주장이 과격했고, 호환성 문제가 있었기 떄문이다. 실제로 SQLite 관련 코드를 수정했다가 다른 서비스나 언어 구현에서 처리가 안 되어 깨지는 사례가 발생했다.&lt;&#x2F;p&gt;
&lt;p&gt;그럼에도 HN 토론에서 많이 언급됐듯이, 이런 레거시는 언젠가 정리해야 한다는 의견에 동의한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;railway-oriented-programming-rop&quot;&gt;Railway Oriented Programming (ROP)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kciter.so&#x2F;posts&#x2F;railway-oriented-programming&#x2F;&quot;&gt;Railway Oriented Programming (ROP)&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;0e.medium.com&#x2F;%EA%B7%B8%EB%9E%98%EC%84%9C-rop%EA%B0%80-%EB%AD%94%EB%8D%B0-%EC%94%B9%EB%8D%95%EC%95%84-railway-oriented-programming-4e8070c04bda&quot;&gt;Railway Oriented Programming이란? (Medium)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Rust의 &lt;code&gt;Result&lt;&#x2F;code&gt;, Kotlin의 &lt;code&gt;Result&lt;&#x2F;code&gt; 도 이 패턴을 사용한다. try-catch와 달리 예외 흐름을 선형적으로 처리할 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;Spring 트랜잭션 같은 기존 패턴과는 잘 맞지 않아서 실무에서 자주 쓰진 않았다.
실패 경로를 명시적으로 다뤄야 할 때 써본 적은 있지만, 돌이켜보면 크고 복잡한 코드의 레거시를 갈아엎지 못하던 상황에서 나온 코드였다.&lt;&#x2F;p&gt;
&lt;p&gt;ROP 자체는 좋다고 생각하지만, JVM 생태계는 프레임워크&#x2F;라이브러리가 예외 기반이라, 제한된 영역이 아니라면 ROP 스타일이 잘 맞지 않아 보인다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;joheun-dijainiran-gesyutalteuwa-mildoro-alabogi&quot;&gt;좋은 디자인이란? - 게슈탈트와 밀도로 알아보기&lt;&#x2F;h3&gt;
&lt;p&gt;색이나 예쁜 걸 말하는 게 아니라 레이아웃이나 어떻게 정보를 전달할 것인가를 다루는 내용들.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;matthewstrom.com&#x2F;writing&#x2F;ui-density&quot;&gt;UI Density (Matthew Ström)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=43925732&quot;&gt;HackerNews 토론&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brunch.co.kr&#x2F;@artneighbor&#x2F;78&quot;&gt;게슈탈트 심리학과 UI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;레이아웃을 잘 꾸미고, 서비스 특성에 따라 밀도를 조절하기&lt;&#x2F;p&gt;
&lt;h3 id=&quot;frameworkless-frontend-development-seuteodi&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gdsc-ssu&#x2F;2023-FE-with-no-framework&quot;&gt;Frameworkless Frontend Development 스터디&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;프레임워크 없이 프론트엔드 개발하기. 내용은 괜찮은데 책으로 보면 불편할 듯. 블로그로 원서를 찾아보거나 직접 구현 분석하는 게 더 나을 것 같다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Apress&#x2F;frameworkless-front-end-development&#x2F;tree&#x2F;master&quot;&gt;원본 코드 (GitHub)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;(아래 작업 파트에 누가 스터디한 레포 포크해서 개인적으로 정리한 레포를 적어둠.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;coejeoghwareul-wihan-algorijeum&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;algorithmsbook.com&#x2F;optimization&#x2F;#download&quot;&gt;최적화를 위한 알고리즘&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.hada.io&#x2F;topic?id=24757&quot;&gt;GeekNews&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;algorithmsbooks&#x2F;algforopt-notebooks&quot;&gt;Jupyter Notebook 버전&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;최적화 문제를 다루는 알고리즘 책. 무료로 공개되어 있고, Julia 언어로 구현되어 있다. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;namu.wiki&#x2F;w&#x2F;Julia&quot;&gt;Julia&lt;&#x2F;a&gt; 나무위키)&lt;&#x2F;p&gt;
&lt;p&gt;다만 이런 의견도 있음을 주의하고 보기.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;책에 Firefly, Cuckoo Search 같은 메타휴리스틱이 포함된 걸 보고 놀람. 이 알고리즘들은 학계에서 신뢰받지 못하고, ITOR 논문에서도 비판받았음&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;top-github-users-in-south-korea&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gayanvoice&#x2F;top-github-users&#x2F;blob&#x2F;main&#x2F;markdown&#x2F;public_contributions&#x2F;south_korea.md&quot;&gt;Top GitHub Users in South Korea&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;깃헙 유저들 나라 별 기여&#x2F;팔로워 순 순위를 모아놓은 레포에서 한국인끼리 모아둔 페이지.&lt;&#x2F;p&gt;
&lt;p&gt;내리다 보면 아는 사람이나 유명한 블로그 쓰는 사람들이 종종 보인다.&lt;&#x2F;p&gt;
&lt;p&gt;내 계정도 있는데, 팔로워, 기여 수 조건이 있어 아슬아슬하게 들어가있다. 기여는 학교에서 안 공개 프로젝트 덕에 높게 나오는거 같다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;oopyi-35nyeon-silsu-casey-muratori-balpyoyeongsang-in-bsc-2025&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=wo84LFzx5nI&quot;&gt;OOP의 35년 실수 - Casey Muratori 발표영상 In BSC 2025&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;claude.ai&#x2F;share&#x2F;3f5044c9-e393-4f97-a177-f10879c5201c&quot;&gt;Claude AI 요약&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Casey Muratori가 OOP의 구조적 문제점을 지적한 강연. 논쟁적이지만 생각해볼 거리를 많이 던져준다.&lt;&#x2F;p&gt;
&lt;p&gt;ECS, Fat Struct 같은 패턴이 이전부터 있었고, 특정 상황에서는 이게 더 적절하다는 것.&lt;&#x2F;p&gt;
&lt;p&gt;현재의 OOP가 범용 대규모 프로그래밍에 유리하다는 인식과 달리 초기에는 제한된 도메인(분산 시스템)의 소규모 팀에서 탄생한 개념이라는게 인상깊었음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;seoneonjeog-peurogeuraeminge-daehan-caggaggwa-ohae&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;evan-moon.github.io&#x2F;2025&#x2F;09&#x2F;07&#x2F;declarative-programming-misconceptions-and-essence&#x2F;&quot;&gt;선언적 프로그래밍에 대한 착각과 오해&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;선언형 프로그래밍이 무엇인지, 왜 오해받는지에 대한 깊이 있는 분석.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-every-programmer-should-know-about-memory&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;250967&#x2F;&quot;&gt;What Every Programmer Should Know About Memory&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.freebsd.org&#x2F;~lstewart&#x2F;articles&#x2F;cpumemory.pdf&quot;&gt;공식 PDF (114페이지)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.com&#x2F;search?q=ycombinator+%22What+Every+Programmer+Should+Know+About+Memory%22&quot;&gt;구글 검색하기&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;메모리 계층 구조, 캐시, NUMA 등 하드웨어 수준의 메모리 동작 원리를 다룬 유명한 글. 114페이지의 방대한 분량이라 모든 내용을 알아야 하는 건 아니라는 주장이 HN에서 꾸준히 나온다. (오래된 글이라 그런지 인용이 너무 많이 되서 해커뉴스 링크들를 주기보다는 그냥 구글에 검색하는게 나을 정도) 그럼에도 일부 핵심 개념은 성능 최적화를 할 때 중요하므로, 필요할 때 참고하면 좋을 듯.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;thread-dump-the-simple-tool-for-debugging-java-applications-in-production-by-gustav-karlsson&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blogg.bekk.no&#x2F;thread-dump-the-simple-tool-for-debugging-java-applications-in-production-1cfed0d0d120&quot;&gt;Thread dump — the simple tool for debugging Java-applications in production | by Gustav Karlsson&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;프로덕션 환경에서 Java 애플리케이션의 성능 문제나 데드락을 진단하는 실용적인 방법. Thread dump를 어떻게 수집하고 분석하는지 단계별로 설명한다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;naega-mandeun-bangeo-yutil-hamsu-5jong-seteu-popeumeosin&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.popekim.com&#x2F;ko&#x2F;2025&#x2F;10&#x2F;11&#x2F;defensive-assertion-utils.html&quot;&gt;내가 만든 방어 유틸 함수 5종 세트 | 포프머신&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;서버에서 유용한 커스텀 Assert 함수 패턴. 로깅, 슬랙 알림, 에러 로그, 심지어 사이렌 등으로 알리고, 중요도에 따라 다르게 구성한다.&lt;&#x2F;p&gt;
&lt;p&gt;코드로써 의미가 명확하고 가독성이 좋다. 테스트까진 아니지만 효율적이고 그에 준하는 효과 (가정이 깨지는 순간 파악, 의도적인 범위&#x2F;제한 명시)를 가진다.&lt;&#x2F;p&gt;
&lt;p&gt;좋아보인다. 도입해볼만한 가치가 있을 듯.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reflections-on-trusting-trust-ken-thompson&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cesarsotovalero.net&#x2F;blog&#x2F;revisiting-ken-thompson-reflection-on-trusting-trust.html&quot;&gt;Reflections on Trusting Trust - Ken Thompson&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;309fe1a139f818284558822277b8ca70&quot;&gt;한국어 AI 번역 (Gist)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ken Thompson의 유명한 튜링상 수상 강연. 컴파일러에 백도어를 심어도 소스 코드 검사만으로는 발견할 수 없다는 걸 보여준 논문.&quot;신뢰를 어디까지 확장할 수 있는가?&quot;라는 근본적인 보안 질문을 던진다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-surprising-truth-about-pixels-and-accessibility&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.joshwcomeau.com&#x2F;css&#x2F;surprising-truth-about-pixels-and-accessibility&#x2F;&quot;&gt;The Surprising Truth About Pixels and Accessibility&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;px, em, rem 단위를 언제 어떻게 사용해야 하는지에 대한 실용적인 가이드. 특히 사용자의 접근성 관점에서 설명함.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;대부분 상황: rem. 사용자 기본 폰트 크기 설정(=사용자가 의도한 크기)에 따라 크기가 바뀌기 떄문&lt;&#x2F;li&gt;
&lt;li&gt;부모&#x2F;자신의 font-size에 비례해야 할 때: em&lt;&#x2F;li&gt;
&lt;li&gt;고정된 크기: px&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;you-no-longer-need-javascript-hackernews&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lyra.horse&#x2F;blog&#x2F;2025&#x2F;08&#x2F;you-dont-need-js&#x2F;&quot;&gt;You no longer need JavaScript&lt;&#x2F;a&gt; | &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12690842&quot;&gt;HackerNews&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;현대 CSS와 HTML만으로 대부분의 웹 기능을 구현할 수 있다는 점을 보여주는 글.&lt;&#x2F;p&gt;
&lt;p&gt;지금 이 글을 보여주는 개인 블로그를 만들 때 사용한 css 작성 스타일에도 영향을 주었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hypermedia-systems&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hypermedia.systems&#x2F;&quot;&gt;Hypermedia Systems&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;htmx 제작자 Carson Gross가 쓴 책이다.
REST 아키텍처의 원래 의도를 설명하고, SPA 프레임워크 없이 hypermedia(HTML) 기반으로 웹 애플리케이션을 구축하는 방법을 다룬다.&lt;&#x2F;p&gt;
&lt;p&gt;무료로 온라인에서 읽을 수 있다.&lt;&#x2F;p&gt;
&lt;p&gt;추가: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;4682b1346fa3eb6316e78f2f37554873&quot;&gt;Single HTML로 만드는 코드 - Gist&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;관련해서 잘 정리된 글: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;parksb.github.io&#x2F;article&#x2F;43.html&quot;&gt;웹은 왜 복잡해졌나? -모던 웹의 복잡성과 하이퍼미디어 시스템&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jageob&quot;&gt;작업&lt;&#x2F;h2&gt;
&lt;p class=&quot;section-description&quot;&gt;학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;p&gt;&lt;h3 id=&quot;neteuweokeueseo-macgwa-ipga-bunridoen-iyu&quot;&gt;네트워크에서 MAC과 IP가 분리된 이유&lt;&#x2F;h3&gt;
&lt;p&gt;&quot;Rust in Action&quot; p.345를 보고 궁금해져서 찾아본 내용.&lt;&#x2F;p&gt;
&lt;p&gt;IP와 MAC은 다른 용도를 가지고 서로 다른 단체에 의해 다른 연도에 만들어졌다:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;MAC: LAN 내부 하드웨어의 통신용&lt;&#x2F;li&gt;
&lt;li&gt;IP: 네트워크 간 통신용, 먼저 만들어졌다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;두 가지를 연결하기 위해 ARP가 등장했다. 참고로 MAC과 IP가 항상 같이 쓰이는 건 아니다. (MAC 주소 개념을 사용하지 않거나, IP 주소 ↔ 링크 주소 매핑이 다른 방식으로 처리되는 경우도 있음)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.perplexity.ai&#x2F;search&#x2F;daeum-naeyongeul-dwisbadcimhan-NuIVwuwVS666X3VvAJEX.A#0&quot;&gt;Perplexity 검색 결과&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;877cc0530c38d056ed988525a2392469&quot;&gt;정리 Gist&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;frameworkless-frontend-development-guhyeon-yeonseub&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;forked-2023-FE-with-no-framework&quot;&gt;Frameworkless Frontend Development 구현 연습&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gdsc-ssu&#x2F;2023-FE-with-no-framework&quot;&gt;원본 스터디 레포&lt;&#x2F;a&gt;를 fork해서 직접 구현해본 프로젝트. 프레임워크 없이 순수 JavaScript로 프론트엔드 애플리케이션을 만들면서 라우팅, 상태 관리, 컴포넌트 시스템 등의 기본 원리를 학습했다.&lt;&#x2F;p&gt;
&lt;p&gt;프레임워크가 내부적으로 어떻게 동작하는지 이해하고, 실제로 직접 구현해보면서 웹 플랫폼의 기초를 다질 수 있었다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;chip-8-emyulreiteo-c-eoneo&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;c-chip-8&quot;&gt;CHIP-8 에뮬레이터 (C 언어)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;C 언어로 CHIP-8 에뮬레이터를 구현한 프로젝트.&lt;&#x2F;p&gt;
&lt;p&gt;CPU 명령어 해석, 메모리 관리를 직접 만들면서 이해할 수 있었음.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;awesome-for-me&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;YangSiJun528&#x2F;awesome-for-me&quot;&gt;awesome-for-me&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;개인적으로 유용하다고 생각하는 자료들을 정리한 저장소.&lt;&#x2F;p&gt;
&lt;p&gt;지금은 개인 디스코드나 월간 기록으로 자료 관리 방식을 바꿔서 더 이상 업데이트하지는 않고 있음.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[월간 기록] 시리즈 소개</title>
          <pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/monthly-log-introduction/</link>
          <guid>https://sijun-yang.com/blog/monthly-log-introduction/</guid>
          <description xml:base="https://sijun-yang.com/blog/monthly-log-introduction/">&lt;p&gt;평소 관심 가는 여러 자료를 수집하고 학습하는데, 관심사가 자주 바뀌다 보니 시간이 지나면 흩어지거나 까먹곤 한다.&lt;&#x2F;p&gt;
&lt;p&gt;자잘한 활동을 기록하고 공유도 할 겸 유용한 자료, 회고, 일상, 학습 기록 등을 한곳에 남겨두는 &quot;월간 기록&quot; 시리즈를 만들었다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pomaes&quot;&gt;포맷&lt;&#x2F;h2&gt;
&lt;p&gt;매달 마지막 날을 기준으로 업로드하며, 다음과 같은 구성으로 이루어진다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;수집&lt;&#x2F;strong&gt;: 그 달에 발견한 흥미롭거나 유용했던 자료들&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;작업&lt;&#x2F;strong&gt;: 학습, 개발, 실험 등 직접 손댄 것들&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;짧은 생각&lt;&#x2F;strong&gt;: 근황과 요즘 하는 생각&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;내부 형식은 자유롭게 작성한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mogjeog&quot;&gt;목적&lt;&#x2F;h2&gt;
&lt;p&gt;월간 기록을 시작한 이유는 활동 기록도 있지만, 자료 선별 목적도 있다.&lt;&#x2F;p&gt;
&lt;p&gt;개인 디스코드 채널에 자료를 모아왔는데, 정리되어있지 않은데다가 3년이 넘으니 찾기 어려워졌다.
그래서 수집 방식은 유지하되, 월말에 참고할 만한 것만 선별해 따로 기록하기로 했다.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>동기&#x2F;비동기, 블로킹&#x2F;논블로킹 개념은 어디서부터 잘못되었나</title>
          <pubDate>Thu, 11 Dec 2025 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/blocking-nonblocking-sync-async-misconceptions/</link>
          <guid>https://sijun-yang.com/blog/blocking-nonblocking-sync-async-misconceptions/</guid>
          <description xml:base="https://sijun-yang.com/blog/blocking-nonblocking-sync-async-misconceptions/">&lt;p&gt;여러 개발 관련 글에서 Blocking&#x2F;Non-blocking과 Sync&#x2F;Async를 설명할 때면 항상 등장하는 2x2 매트릭스가 있다. 4개의 조합으로 나누어 설명하는 이 표를 한 번쯤은 보았을 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;sync-async-matrix.png&quot; alt=&quot;Blocking&#x2F;Non-blocking, Sync&#x2F;Async 비교 매트릭스&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;이 매트릭스에서 가장 이해하기 어려운 부분은 Blocking + Async 조합이다. 많은 블로그에서 이 조합을 설명하려고 시도하지만, 나는 대부분 억지스러운 설명이라는 인상을 받았다.&lt;&#x2F;p&gt;
&lt;p&gt;최근 이 개념을 다시 공부하다가 이러한 설명은 올바르지 않다는 사실을 알게 되었다. 우리가 그동안 별 의심없이 받아들였던 이 설명이 잘못된 이유를 말해보고자 한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jalmosdoen-seolmyeongyi-culceo&quot;&gt;잘못된 설명의 출처&lt;&#x2F;h2&gt;
&lt;p&gt;이러한 매트릭스 기반의 설명의 시작은 IBM Developer의 2006년 글 &quot;Boost application performance using asynchronous I&#x2F;O&quot;인 것으로 보인다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;ibm-io-comparison.png&quot; alt=&quot;원래 글의 비교&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;IBM의 글은 리눅스 커널의 AIO(Asynchronous I&#x2F;O) API를 소개하면서 sync&#x2F;async와 blocking&#x2F;non-blocking을 조합해 4가지로 구분했다.&lt;&#x2F;p&gt;
&lt;p&gt;그러나 이 글의 구분은 POSIX 표준 정의와는 다르다. 이 글에선 &lt;code&gt;select&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;poll&lt;&#x2F;code&gt;를 blocking + async의 조합으로 소개하지만, POSIX 표준 정의에는 이런 조합이 등장할 수 없다.&lt;&#x2F;p&gt;
&lt;p&gt;IBM의 글은 리눅스 커널의 AIO API를 소개하는 글이다. 리눅스 커널은 POSIX 표준을 구현하므로, 커널 레벨 I&#x2F;O를 논한다면 POSIX 정의와 일관되어야 한다. 그러나 IBM의 분류는 POSIX 표준과 일치하지 않는다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;posix-pyojunyi-silje-jeongyi&quot;&gt;POSIX 표준의 실제 정의&lt;&#x2F;h2&gt;
&lt;p&gt;POSIX 표준&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;과 리처드 스티븐스(W. Richard Stevens)의 책 Unix Network Programming&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;을 살펴보면 명확한 정의를 찾을 수 있다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Synchronous I&#x2F;O: I&#x2F;O 작업이 완료될 때까지 요청 프로세스가 blocked&lt;&#x2F;li&gt;
&lt;li&gt;Asynchronous I&#x2F;O: 요청 프로세스가 blocked되지 않음&lt;&#x2F;li&gt;
&lt;li&gt;Blocking: 요청한 동작이 완료될 때까지 함수 호출이 대기&lt;&#x2F;li&gt;
&lt;li&gt;Non-blocking: 요청한 동작을 즉시 완료할 수 없으면 지연 없이 반환&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;여기서 중요한 점은 I&#x2F;O 작업 완료의 의미다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unix-i-o-modelyi-du-dangye&quot;&gt;Unix I&#x2F;O 모델의 두 단계&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x2F;O 작업은 일반적으로 두 단계로 이루어진다:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;데이터 준비 단계 - 디스크에서 데이터를 읽거나 네트워크에서 패킷이 도착하기를 기다린다. 데이터가 준비되면 커널 버퍼로 복사된다.&lt;&#x2F;li&gt;
&lt;li&gt;데이터 복사 단계 - 커널 버퍼에서 애플리케이션 버퍼로 데이터를 복사한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;스티븐스는 Unix에서 사용 가능한 5가지 I&#x2F;O 모델을 다음과 같이 구분한다. 이 모델은 커널이 I&#x2F;O 준비와 수행을 어떻게 관여하느냐에 따른 대표적인 분류이다. 상호 배타적인 조합표를 의미하지 않는다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-blocking-i-o&quot;&gt;1. Blocking I&#x2F;O&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;blocking-io-model.png&quot; alt=&quot;Blocking I&#x2F;O 모델의 Flow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;가장 흔한 I&#x2F;O 모델이다. &lt;code&gt;read()&lt;&#x2F;code&gt; 시스템 콜을 호출하면 데이터가 준비되고 복사가 완료될 때까지 프로세스가 block된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-non-blocking-i-o&quot;&gt;2. Non-blocking I&#x2F;O&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;nonblocking-io-model.png&quot; alt=&quot;Non-blocking I&#x2F;O 모델의 Flow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;O_NONBLOCK&lt;&#x2F;code&gt; 플래그를 설정하면 데이터가 준비되지 않았을 때 &lt;code&gt;EAGAIN&lt;&#x2F;code&gt; 에러와 함께 즉시 반환한다. 하지만 데이터가 준비되면 복사하는 동안은 여전히 block된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-i-o-multiplexing&quot;&gt;3. I&#x2F;O Multiplexing&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;io-multiplexing-model.png&quot; alt=&quot;I&#x2F;O Multiplexing 모델의 Flow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;select()&lt;&#x2F;code&gt;나 &lt;code&gt;poll()&lt;&#x2F;code&gt;을 사용해 여러 file descriptor를 동시에 감시한다. 준비된 fd에 대해 &lt;code&gt;read()&lt;&#x2F;code&gt;를 호출할 때 여전히 block된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-signal-driven-i-o&quot;&gt;4. Signal-Driven I&#x2F;O&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;signal-driven-io-model.png&quot; alt=&quot;Signal-Driven I&#x2F;O 모델의 Flow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;SIGIO&lt;&#x2F;code&gt; 신호를 등록하고 데이터가 준비되면 신호를 받는다. 신호를 받은 후 &lt;code&gt;read()&lt;&#x2F;code&gt;를 호출하면 여전히 block된다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-asynchronous-i-o&quot;&gt;5. Asynchronous I&#x2F;O&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;async-io-model.png&quot; alt=&quot;Asynchronous I&#x2F;O 모델의 Flow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;진정한 비동기 I&#x2F;O다. &lt;code&gt;aio_read()&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;는 즉시 반환되고, 커널이 백그라운드에서 두 단계를 모두 처리한 후 완료를 통지한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;synchronous-vs-asynchronousyi-haegsim&quot;&gt;Synchronous vs Asynchronous의 핵심&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;blog&#x2F;io-models-comparison.png&quot; alt=&quot;5가지 I&#x2F;O 모델의 비교표&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;스티븐스는 Unix Network Programming에서 이 모델들의 동기&#x2F;비동기 여부를 명확하게 구분한다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;POSIX defines these two terms as follows:&lt;&#x2F;p&gt;
&lt;p&gt;A synchronous I&#x2F;O operation causes the requesting process to be blocked until that I&#x2F;O operation completes.&lt;br &#x2F;&gt;
An asynchronous I&#x2F;O operation does not cause the requesting process to be blocked.&lt;br &#x2F;&gt;
Using these definitions, the first four I&#x2F;O models (blocking, nonblocking, I&#x2F;O multiplexing, and signal-driven I&#x2F;O) are all synchronous because the actual I&#x2F;O operation (recvfrom) blocks the process. Only the asynchronous I&#x2F;O model matches the asynchronous I&#x2F;O definition.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;다음과 같이 번역할 수 있다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;POSIX는 이 두 용어를 다음과 같이 정의한다:&lt;&#x2F;p&gt;
&lt;p&gt;동기 I&#x2F;O(synchronous I&#x2F;O) 작업은 해당 I&#x2F;O 작업이 완료될 때까지 요청한 프로세스를 블로킹한다.&lt;br &#x2F;&gt;
비동기 I&#x2F;O(asynchronous I&#x2F;O) 작업은 요청한 프로세스를 블로킹하지 않는다.&lt;br &#x2F;&gt;
이 정의에 따르면, 처음 네 가지 I&#x2F;O 모델(블로킹 I&#x2F;O, 논블로킹 I&#x2F;O, I&#x2F;O 멀티플렉싱, 시그널 기반 I&#x2F;O)은 모두 동기 I&#x2F;O에 해당한다. 실제 I&#x2F;O 연산인 &lt;code&gt;recvfrom&lt;&#x2F;code&gt; 호출이 프로세스를 블로킹하기 때문이다.
오직 비동기 I&#x2F;O 모델만이 POSIX에서 정의한 비동기 I&#x2F;O에 해당한다.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;5gaji-i-o-modelyi-donggi-bidonggi-bunryu&quot;&gt;5가지 I&#x2F;O 모델의 동기&#x2F;비동기 분류&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;I&#x2F;O 모델&lt;&#x2F;th&gt;&lt;th&gt;Blocking&#x2F;Non-blocking&lt;&#x2F;th&gt;&lt;th&gt;Sync&#x2F;Async&lt;&#x2F;th&gt;&lt;th&gt;1단계 Block&lt;&#x2F;th&gt;&lt;th&gt;2단계 Block&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Blocking I&#x2F;O&lt;&#x2F;td&gt;&lt;td&gt;Blocking&lt;&#x2F;td&gt;&lt;td&gt;Synchronous&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Non-blocking I&#x2F;O&lt;&#x2F;td&gt;&lt;td&gt;Non-blocking&lt;&#x2F;td&gt;&lt;td&gt;Synchronous&lt;&#x2F;td&gt;&lt;td&gt;No (폴링)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;I&#x2F;O Multiplexing&lt;&#x2F;td&gt;&lt;td&gt;Blocking&lt;&#x2F;td&gt;&lt;td&gt;Synchronous&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Signal-driven I&#x2F;O&lt;&#x2F;td&gt;&lt;td&gt;Non-blocking&lt;&#x2F;td&gt;&lt;td&gt;Synchronous&lt;&#x2F;td&gt;&lt;td&gt;No (신호)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Asynchronous I&#x2F;O&lt;&#x2F;td&gt;&lt;td&gt;Non-blocking&lt;&#x2F;td&gt;&lt;td&gt;Asynchronous&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;앞의 네 가지 모델은 모두 데이터 복사 단계(2단계)에서 block된다. 따라서 POSIX 정의상 모두 synchronous다. 오직 asynchronous I&#x2F;O만이 두 단계 모두에서 block되지 않는다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wae-select-neun-synchronousinga&quot;&gt;왜 &lt;code&gt;select()&lt;&#x2F;code&gt;는 synchronous인가?&lt;&#x2F;h3&gt;
&lt;p&gt;자료조사 과정에서 본 여러 자료에서 &lt;code&gt;select()&lt;&#x2F;code&gt;를 asynchronous로 설명하는 경우를 많이 보았다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;select()&lt;&#x2F;code&gt;는 여러 I&#x2F;O를 동시에 처리할 수 있어서 비동기처럼 보이지만, 실제로는 다음과 같이 동작한다:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;프로세스가 감시할 파일 디스크립터 집합을 준비한다.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;select()&lt;&#x2F;code&gt;는 각 파일 디스크립터가 I&#x2F;O를 수행해도 블로킹되지 않을 상태인지를 알려준다.&lt;&#x2F;li&gt;
&lt;li&gt;준비된 파일 디스크립터에 대해 애플리케이션이 &lt;code&gt;read()&lt;&#x2F;code&gt;를 직접 호출한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;이때 &lt;code&gt;read()&lt;&#x2F;code&gt; 호출은 시스템 콜이 완료될 때까지 호출자를 반환하지 않으며, POSIX 정의상 요청한 프로세스를 블로킹하므로 synchronous가 된다.&lt;&#x2F;p&gt;
&lt;p&gt;멀티스레드 환경에서도 마찬가지다. I&#x2F;O를 수행하는 스레드는 시스템 콜이 완료될 때까지 블로킹되며, POSIX 정의에 따르면 이는 동기 I&#x2F;O다.
스레드 분리는 애플리케이션 레벨의 동시성 전략일 뿐이다. 커널의 I&#x2F;O 모델을 바꿀 수는 없다.&lt;&#x2F;p&gt;
&lt;p&gt;Linux man page도 &lt;code&gt;select&lt;&#x2F;code&gt;를 &quot;synchronous I&#x2F;O multiplexing&quot;으로 명시하고 있다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 반면 &lt;code&gt;io_uring&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;이나 POSIX &lt;code&gt;aio_&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-2&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 함수들은 &quot;Asynchronous I&#x2F;O&quot;로 구분한다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keoneol-i-o-gaenyeomgwa-peurogeuraeming-modelyi-hondong&quot;&gt;커널 I&#x2F;O 개념과 프로그래밍 모델의 혼동&lt;&#x2F;h2&gt;
&lt;p&gt;IBM의 글은 리눅스 커널 레벨 I&#x2F;O를 다루는 기술 문서다. 커널 레벨에서 이 용어들은 POSIX 표준에 따라 엄밀하게 정의된다.
반면 애플리케이션 레벨에서는 동일한 용어가 더 느슨하고 범용적인 의미로 사용된다.
(커널은 프로세스의 실행 흐름을 정확히 제어해야 하므로 용어가 엄밀하게 정의되지만,
수많은 라이브러리와 프레임워크가 독립적으로 개발되는 애플리케이션 레벨의 라이브러리&#x2F;프레임워크, 언어 등은 용어 통일이 현실적으로 불가능하다.)&lt;&#x2F;p&gt;
&lt;p&gt;하지만 IBM의 글이 널리 인용되면서 두 가지 문제가 발생했다.&lt;&#x2F;p&gt;
&lt;p&gt;첫째, 분류 방식이 POSIX 표준 정의와 정확히 일치하지 않았다. 커널 API를 다루는 글임에도 커널이 따르는 표준과 다른 기준을 사용했고,
이 설명이 반복 인용되면서 표준과 다른 내용이 사실처럼 확산되었다.&lt;br &#x2F;&gt;
둘째, 이후 수많은 블로그와 기술 문서들이 이 2×2 매트릭스를 인용하면서 원래의 맥락을 잃었다.
커널 레벨 I&#x2F;O를 설명하기 위한 용어가 애플리케이션 레벨의 프로그래밍 모델이나 아키텍처의 설명까지 무분별하게 적용되었다.&lt;&#x2F;p&gt;
&lt;p&gt;대표적인 오해는 Node.js + MySQL 드라이버의 예시다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Node.js + MySQL은 Blocking + Async의 예시다. Node.js는 비동기인데 MySQL 드라이버가 블로킹이라서…”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;이 설명은 서로 다른 레벨의 개념을 혼합한 것이다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js의 비동기: 이벤트 루프 기반의 프로그래밍 모델&lt;&#x2F;li&gt;
&lt;li&gt;MySQL 드라이버의 블로킹: 라이브러리 차원의 API 구현 방식&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;이는 커널 레벨의 I&#x2F;O 동작과는 직접적인 관련이 없으며, 애초에 IBM 문서가 다루던 맥락과도 다르다.
이처럼 추상화 레벨이 다른 개념들을 구분 없이 동일한 용어로 설명하다 보니, 개념적 혼란이 발생할 수밖에 없다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;peurogeuraeming-modelroseoyi-bidonggigwa-naebu-guhyeon&quot;&gt;프로그래밍 모델로서의 비동기과 내부 구현&lt;&#x2F;h2&gt;
&lt;p&gt;많은 비동기 프로그래밍 모델을 제공하는 프레임워크들이 내부 구현에선 동기 시스템 콜을 사용한다.&lt;&#x2F;p&gt;
&lt;p&gt;Netty는 &quot;asynchronous event-driven&quot; 프레임워크를 표방하지만&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, 실제로는 &lt;code&gt;epoll()&lt;&#x2F;code&gt;이나 &lt;code&gt;kqueue&lt;&#x2F;code&gt; 같은 I&#x2F;O multiplexing을 사용한다. 이들은 POSIX 정의상 synchronous다.&lt;br &#x2F;&gt;
Node.js도 마찬가지다. libuv를 통해 플랫폼별로 최적화된 I&#x2F;O multiplexing을 사용하거나, 파일 시스템 작업의 경우 별도 스레드 풀에서 blocking I&#x2F;O를 수행한다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-9-1&quot;&gt;&lt;a href=&quot;#fn-9&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;br &#x2F;&gt;
이것이 잘못된 설명이나 구현은 아니다. 애플리케이션 개발자 입장에서는 비동기 프로그래밍 모델을 제공받는 것이 중요하지, 내부적으로 어떤 시스템 콜을 사용하는지는 중요하지 않다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gyeolron&quot;&gt;결론&lt;&#x2F;h2&gt;
&lt;p&gt;POSIX 표준에 따르면 I&#x2F;O 모델은 본질적으로 세 가지로 구분할 수 있다.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Blocking Synchronous - 전통적인 blocking I&#x2F;O와 I&#x2F;O multiplexing&lt;&#x2F;li&gt;
&lt;li&gt;Non-blocking Synchronous - non-blocking I&#x2F;O와 signal-driven I&#x2F;O&lt;&#x2F;li&gt;
&lt;li&gt;Asynchronous - 진정한 비동기 I&#x2F;O (POSIX aio, io_uring)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;따라서 Blocking + Async라는 조합은 정의상 존재할 수 없다. Asynchronous는 정의상 어떤 단계에서도 block되지 않기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;물론 애플리케이션 레벨에서는 이 구분이 덜 엄격하다. 프로그래밍 모델로서의 비동기와 시스템 콜 레벨의 비동기는 다른 개념이며, 이를 명확히 구분해야 한다.
Netty나 Node.js 같은 프레임워크가 비동기를 표방하는 것은 애플리케이션 개발자에게 제공하는 프로그래밍 모델을 지칭하는 것이지, POSIX I&#x2F;O 모델의 정의를 따르는 것이 아니다.&lt;&#x2F;p&gt;
&lt;p&gt;중요한 것은 맥락이다. OS나 커널 레벨의 I&#x2F;O를 논할 때와 애플리케이션 레벨의 프로그래밍 패턴을 논할 때, 같은 용어가 다른 의미를 가질 수 있다. 이러한 차이를 인지하고 명확히 구분해서 사용해야 불필요한 혼란을 피할 수 있다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naneun-eoddeohge-gubunhaneunga&quot;&gt;나는 어떻게 구분하는가&lt;&#x2F;h2&gt;
&lt;p&gt;커널 I&#x2F;O 레벨에선 표준의 정의를 따른다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;동기 &#x2F; 비동기: I&#x2F;O 작업이 완료될 때까지 요청 프로세스가 블로킹되는지 여부&lt;&#x2F;li&gt;
&lt;li&gt;블로킹 &#x2F; 논블로킹: 요청한 동작을 즉시 완료할 수 없을 때 함수 호출이 대기하는지 여부&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;다만 시스템 레벨 개발을 주로 하지 않기 때문에, 이 용어를 쓸 일은 많지 않다.
이 레벨에서는 추상적인 용어보다 select, epoll, io_uring 같은 구체적인 시스템 콜 이름으로 대화하는 것이 더 명확하다고 생각한다.&lt;&#x2F;p&gt;
&lt;p&gt;어플리케이션 레벨에선 다음 기준으로 구분한다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;동기 &#x2F; 비동기: 애플리케이션 레벨에서의 프로그래밍 모델, 전체 실행 흐름&lt;&#x2F;li&gt;
&lt;li&gt;블로킹 &#x2F; 논블로킹: 함수 호출이나 개별 작업 단위에서의 동작&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;일반적으로 이 관점에서 이야기한다. 이렇게 구분하면 아키텍처를 설명하거나 문제를 분석할 때 명확하게 생각할 수 있다.&lt;br &#x2F;&gt;
예를 들어, “비동기 모델 환경에서 블로킹 호출을 사용해 전체 실행 흐름에 영향을 주었다.”, “동기 환경이더라도 오래 걸리는 I&#x2F;O를 논블로킹으로 처리해 효율을 높일 수 있다.” 와 같이 모델과 동작을 분리해서 생각할 수 있다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;burog&quot;&gt;부록&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;Boost application performance using asynchronous I&#x2F;O&quot; 를 포함한 IBM Developer의 오래된 글이 아카이브되어 원래 작성 시점을 알 수 없었는데, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cyberciti.biz&#x2F;tips&#x2F;linux-boost-application-performance-using-asynchronous-io.html&quot;&gt;저자의 사이트에서 원본 자료가 링크된 글&lt;&#x2F;a&gt;을 보고 2006년 작성되었다고 추정했다.&lt;&#x2F;p&gt;
&lt;p&gt;IBM의 설명이 한국에만 퍼진 이야기는 아닌 듯 하다. 영어, 중국어나 일본어로 작성된 자료에서도 2x2 매트릭스를 사용해 구분하는 글을 찾아볼 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;조사 과정에서 참고한 자료들이다. 높은 신뢰성을 가지는 문서는 아니지만 개념을 이해하는 데 도움이 되어 남겨두었다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linuxquestions.org&#x2F;questions&#x2F;programming-9&#x2F;asynchronized-i-o-%3D%3D-multiplexing-i-o-467044&#x2F;&quot;&gt;Asynchronized I&#x2F;O vs Multiplexing I&#x2F;O 토론 - Linux Questions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.artima.com&#x2F;articles&#x2F;comparing-two-high-performance-io-design-patterns&quot;&gt;Comparing Two High-Performance I&#x2F;O Design Patterns&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;EJNBLD3X2yg&quot;&gt;비동기 프로그래밍, 비동기 I&#x2F;O, 비동기 커뮤니케이션 - 쉬운코드 (YouTube)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;homoefficio.github.io&#x2F;2017&#x2F;02&#x2F;19&#x2F;Blocking-NonBlocking-Synchronous-Asynchronous&#x2F;&quot;&gt;Blocking-NonBlocking-Synchronous-Asynchronous - 뒤태지존의 끄적거림&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;1pn6010&#x2F;compio_instead_of_tokio_what_are_the_implications&#x2F;&quot;&gt;Tokio와 Compio의 차이: 비동기 모델(epoll vs io_uring) - Reddit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.inflearn.com&#x2F;course&#x2F;%EA%B8%B0%EC%B4%88%ED%83%84%ED%83%84-%EB%8F%85%ED%95%98%EA%B2%8C-java-part3-2&quot;&gt;기초 탄탄! 독하게 시작하는 Java Part 3(하) : 소켓과 파일 I&#x2F;O 강의 | 널널한 개발자 - 인프런&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;M. Tim Jones, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.ibm.com&#x2F;articles&#x2F;l-async&#x2F;&quot;&gt;&quot;Boost application performance using asynchronous I&#x2F;O&quot;&lt;&#x2F;a&gt;, IBM Developer, 2006. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;IEEE Std 1003.1-2024, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9799919799&#x2F;&quot;&gt;&quot;The Open Group Base Specifications Issue 8&quot;&lt;&#x2F;a&gt;, IEEE and The Open Group, 2024. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;IEEE Std 1003.1-2004, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;009695399&#x2F;&quot;&gt;&quot;The Open Group Base Specifications Issue 6&quot;&lt;&#x2F;a&gt;, IEEE and The Open Group, 2004. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;W. Richard Stevens, Bill Fenner, Andrew M. Rudoff, &quot;Unix Network Programming, Volume 1: The Sockets Networking API&quot;, 3rd Edition, Addison-Wesley, 2003. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;예를 들면, I&#x2F;O Multiplexing과 Non-blocking I&#x2F;O 모델을 함께 사용할 수도 있다. &lt;code&gt;select()&lt;&#x2F;code&gt; 함수는 기본적으로 이벤트가 올때까지 wait하는 blocking 함수인데, fb에 &lt;code&gt;O_NONBLOCK&lt;&#x2F;code&gt; 플래그를 활성화 해서 Non-blocking 함수로 동작하게 할 수 있다. 이 경우, 여러 fb를 동시에 감시하면서 데이터의 준비 여부와 무관하게 즉시 반환된다. &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Linux man pages, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;aio.7.html&quot;&gt;&quot;aio(7) - POSIX asynchronous I&#x2F;O overview&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-7-2&quot;&gt;↩2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;Linux man pages, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;select.2.html&quot;&gt;&quot;select(2) - synchronous I&#x2F;O multiplexing&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;Linux man pages, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;io_uring.7.html&quot;&gt;&quot;io_uring(7) - Asynchronous I&#x2F;O facility&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Netty Project, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;netty&#x2F;netty&#x2F;blob&#x2F;4.2&#x2F;README.md&quot;&gt;&quot;Netty v4.2 README&quot;&lt;&#x2F;a&gt;, GitHub &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-9&quot;&gt;
&lt;p&gt;libuv documentation, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.libuv.org&#x2F;en&#x2F;v1.x&#x2F;design.html&quot;&gt;&quot;Design overview&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-9-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Java 배열 인덱스 접근은 정말 O(1)인가?</title>
          <pubDate>Wed, 21 May 2025 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/programming-language-spec-vs-impl/</link>
          <guid>https://sijun-yang.com/blog/programming-language-spec-vs-impl/</guid>
          <description xml:base="https://sijun-yang.com/blog/programming-language-spec-vs-impl/">&lt;p&gt;누군가 개발 커뮤니티에 이런 질문을 올렸다.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Java 배열의 인덱스 접근이 O(1)이라는데, 공식 문서에서 찾을 수가 없어요. 어디서 확인할 수 있나요?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;나도 당연히 O(1)이라고 생각했지만, 막상 &quot;어디에 그렇게 쓰여 있냐&quot;고 물으면 대답하기 어려웠다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;java-baeyeol-indegseu-jeobgeunyi-naebu-dongjag&quot;&gt;Java 배열 인덱스 접근의 내부 동작&lt;&#x2F;h3&gt;
&lt;p&gt;실제로 확인해보자. 다음과 같은 간단한 Java 코드가 있다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;public static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #4078F2;&quot;&gt; array&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C18401;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt;[] intArr&lt;&#x2F;span&gt;&lt;span&gt; = {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; intA&lt;&#x2F;span&gt;&lt;span&gt; = intArr[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A626A4;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E45649;&quot;&gt; intB&lt;&#x2F;span&gt;&lt;span&gt; = intArr[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #986801;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;자바에서 배열이나 사칙연산 같은 기본 기능은 자바 코드 레벨에서 내부 동작을 확인할 수 없다.
&lt;code&gt;java.util.ArrayList&lt;&#x2F;code&gt; 같이 자바 언어로 구현된 표준 라이브러리와 달리, 언어 사양에 의해 동작이 정의되는 더 저수준의 영역이기 때문이다.
그렇다면 배열의 동작을 확인하기 위해선 무엇을 봐야 할까?&lt;&#x2F;p&gt;
&lt;p&gt;먼저 자바 언어 명세(JLS)의 배열 접근 문서&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;를 확인했다. 배열을 어떻게 사용할 수 있는지만 서술하고 있다.
구체적인 구현 방식이나 시간복잡도에 관한 요구사항은 없다.&lt;&#x2F;p&gt;
&lt;p&gt;다음으로 JVM 명세(JVMS)를 확인했다.
JVMS에서는 배열 인덱스 접근 시 어떤 바이트코드가 사용되는지 명시한다. 실제로 사용되는지 확인해보자.&lt;&#x2F;p&gt;
&lt;p&gt;잠깐 바이트코드에 대해 설명하면, Java는 컴파일 시 바이트코드로 변환되고 JVM이 이를 실행한다.
JVM은 스택 기반 가상 머신으로&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, 값을 스택에 쌓고 명령어가 꺼내 연산하는 방식이다.
따라서 자바 프로그램의 실제 동작을 더 확실하게 알기 위해선 바이트코드를 보아야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;위 자바 코드를 컴파일하면 배열 인덱스 접근은 다음과 같은 바이트코드로 변환된다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; intArr[0] 접근&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ALOAD 0      &#x2F;&#x2F; 배열 참조를 스택에 푸시&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ICONST_0     &#x2F;&#x2F; 정수 0을 스택에 푸시 (인덱스)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;IALOAD       &#x2F;&#x2F; 스택에서 배열과 인덱스를 꺼내 해당 요소를 읽음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F; intArr[9] 접근&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ALOAD 0      &#x2F;&#x2F; 배열 참조를 스택에 푸시&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BIPUSH 9     &#x2F;&#x2F; 정수 9를 스택에 푸시 (인덱스)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;IALOAD       &#x2F;&#x2F; 스택에서 배열과 인덱스를 꺼내 해당 요소를 읽음&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;JVMS의 명령어 문서&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;를 보면, &lt;code&gt;IALOAD&lt;&#x2F;code&gt; 명령어는 스택에서 배열 참조와 인덱스를 꺼내 해당 요소를 읽어 스택에 푸시한다고 설명한다.
어떤 스택 조작을 하는지만 서술되어 있다. 어떻게 접근해야 하는지, 시간복잡도가 어떠해야 하는지는 명시하지 않는다.&lt;&#x2F;p&gt;
&lt;p&gt;따라서 JLS와 JVMS 어디에도 &quot;배열 인덱스 접근은 O(1)이어야 한다&quot;는 요구사항은 없다. 이제 남은 건 실제 JVM 구현체를 확인하는 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;OpenJDK를 선택했다. Java SE의 공식 레퍼런스 구현체이며, 대부분의 JVM 구현이 이를 기반으로 하기 때문이다.
OpenJDK는 C++로 구현되어 있다. &lt;code&gt;objArrayOop.hpp&lt;&#x2F;code&gt;와 &lt;code&gt;objArrayOop.inline.hpp&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;를 보면 배열 인덱스 접근의 내부 동작을 알 수 있다.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #383A42; background-color: #FAFAFA;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;다음과 같은 순서로 동작한다.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. base_offset_in_bytes()  -&amp;gt; 배열 헤더 크기&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. sizeof(T) * index       -&amp;gt; 요소 크기 × 인덱스&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3. base() + offset         -&amp;gt; 실제 메모리 주소 계산&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4. oop_load_at(offset)     -&amp;gt; 해당 주소에서 값 로드&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;핵심은 (여타 CS 책에서 배열의 구현 방식을 설명할 때처럼) 포인터 산술 연산이다. 배열의 시작 주소에 오프셋을 더해 직접 메모리에 접근한다.
요소의 개수와 무관하게 상수 시간에 동작한다. 따라서 OpenJDK에서는 O(1)이 맞다.&lt;&#x2F;p&gt;
&lt;p&gt;그러나 Java 언어 명세(JLS)나 JVM 명세(JVMS) 어디에도 &quot;배열 인덱스 접근은 O(1)이어야 한다&quot;는 요구사항은 없었다.
OpenJDK는 O(1)로 동작하지만, 그건 특정 구현체의 선택일 뿐 언어의 보장이 아니다.
다른 JVM 구현체가 같은 방식을 사용한다는 보장은 명세에 없다.
(물론 현실적으로 다른 방식을 쓸 이유는 없다. 배열의 특성상 거의 모든 구현체가 O(1)일 것이다.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;myeongsewa-guhyeonyi-gubun&quot;&gt;명세와 구현의 구분&lt;&#x2F;h3&gt;
&lt;p&gt;프로그래밍 언어는 크게 두 레벨로 나뉜다.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;명세(Specification): 언어가 어떻게 동작해야 하는지 정의한 문서. 문법, 타입 시스템, 의미론 등을 규정한다.&lt;&#x2F;li&gt;
&lt;li&gt;구현(Implementation): 명세를 실제로 실행 가능하게 만든 컴파일러나 런타임. 명세가 정의하지 않은 부분은 구현체가 자유롭게 결정한다.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Java의 명세는 JLS(Java Language Specification), JVMS(Java Virtual Machine Specification)이다. 구현은 OpenJDK, Amazon Corretto, Azul Zulu 등이 존재한다. 다양한 JDK 종류의 차이를 알아보려면 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;whichjdk.com&#x2F;&quot;&gt;Which Version of JDK Should I Use?&lt;&#x2F;a&gt;를 참고하자.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;대부분의 성능과 관련된 부분은 명세가 아닌 구현이 결정한다. 흔히 알고리즘 문제에서의 시간 복잡도, 공간 복잡도와 같은 것들은 구현이 결정하게 된다.&lt;&#x2F;p&gt;
&lt;p&gt;프로그래밍 언어의 이러한 점은 Database의 질의형 언어(Query Language)와도 비슷한 점이라고 생각하는데, 내부 구현을 명세에 숨김으로써 자유롭게 기존 동작을 유지하면서 런타임의 최적화를 할 수 있기 때문이다.
예시로 Java는 GC 알고리즘이 계속 발전하고 있으며, Netflix는 Java의 버전을 8에서 17로 업그레이드하면서 약 20%의 CPU 사용률을 향상할 수 있었다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 또한 언어 명세의 수정 없이 Virtual Thread가 도입되기도 했다.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;(OpenJDK의) Java 배열 인덱스 접근이 O(1)이다&quot; 라는 말에서 OpenJDK나 다른 구현체의 이름이 빠진다면 정확하지 않은 말이다.
하지만 이런 내용을 일일이 지적하는 건 소모적인 일이다.&lt;&#x2F;p&gt;
&lt;p&gt;대부분의 개발자가 표준이나 사실상(de facto) 표준인 구현체를 사용한다. Java 개발자가 OpenJDK 계열을 쓰고, 거의 모든 Python 개발자가 CPython을 쓴다.
따라서 일상적인 상황에서는 암묵적으로 가장 표준에 가까운 구현체를 의미한다고 이해해도 무방할 것이다.&lt;&#x2F;p&gt;
&lt;p&gt;그럼에도 다른 런타임이나 구현체 간 차이를 분석하거나 이해하기 위해선 이러한 사실을 알고 있어야 한다.&lt;&#x2F;p&gt;
&lt;p&gt;C는 이 구분이 특히 중요한 언어다. 다양한 하드웨어에서 동작해야 하고, 수십 개의 컴파일러 구현체가 존재한다.
C 표준은 Undefined Behavior (UB), Unspecified Behavior (UsB), Implementation-defined Behavior (IdB)를 구분한다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-9-1&quot;&gt;&lt;a href=&quot;#fn-9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
이 때문에 GCC에서 잘 돌던 코드가 Clang에서 다르게 동작하거나, 최적화 옵션에 따라 결과가 달라질 수 있다.
(이처럼 C는 문법에서 많은 함정을 가지고 있는데, 관심이 있다면 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proofby.ac&#x2F;teaching-c&#x2F;&quot;&gt;C&#x2F;C++를 가르치기 전에 생각해 보기 - finalchild&lt;&#x2F;a&gt;를 한 번 읽어보는걸 추천한다.)&lt;&#x2F;p&gt;
&lt;p&gt;반면 C 이후에 설계된 현대 언어들은 명세가 훨씬 엄격하다. 그래도 여전히 이 구분이 필요한 순간들이 있다.
Node.js의 대항마로 Bun이 등장했을 때, &quot;Bun이 Node.js와 뭐가 다른가?&quot;라는 질문에 답하려면 명세와 구현의 구분이 필요하다.
JavaScript(ECMAScript)는 언어 명세고, Node.js와 Bun은 그 구현체다. 이벤트 루프나 파일 시스템 API는 JavaScript 명세가 아니라 런타임 구현이다. Bun이 빠른 이유는 JavaScript 언어가 달라서가 아니라, 런타임 구현이 다르기 때문이다.&lt;&#x2F;p&gt;
&lt;p&gt;Python도 비슷하다. PyPy는 CPython과 달리 JIT 컴파일을 제공해 CPU Bound 작업에서 유리하다.
심지어 JVM 위에서 실행되는 Jython이라는 런타임도 있다. 이러한 차이는 Python 명세가 실행 환경을 규정하지 않기 때문에 가능하다.
Java의 GraalVM Native Image를 사용하면 JVM 없이 네이티브 바이너리로 컴파일할 수 있다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-10-1&quot;&gt;&lt;a href=&quot;#fn-10&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 이 경우 JVM의 동작을 전제로 한 코드(리플렉션 등)가 제한될 수 있다는 점을 예측할 수 있고, 실제로도 그렇다.&lt;&#x2F;p&gt;
&lt;p&gt;또한 프로그래밍 언어의 구현체는 OS와 런타임 버전에 따라 동작이 달라질 수 있다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-11-1&quot;&gt;&lt;a href=&quot;#fn-11&quot;&gt;11&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; 보안 취약점 문서나 버그 리포트에서 환경 명시가 필수인 이유다.&lt;&#x2F;p&gt;
&lt;p&gt;이처럼 명세와 구현은 다르다. 프로그래밍 언어와 런타임의 성능&#x2F;특징을 올바르게 논하기 위해서는 이를 이해하는 것이 필요하다.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-12-1&quot;&gt;&lt;a href=&quot;#fn-12&quot;&gt;12&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;specs&#x2F;jls&#x2F;se25&#x2F;html&#x2F;jls-15.html#jls-15.10.3&quot;&gt;&quot;JLS 15.10.3 - Array Access Expressions&quot;&lt;&#x2F;a&gt;, Java Language Specification SE 25 &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;specs&#x2F;jvms&#x2F;se25&#x2F;html&#x2F;jvms-2.html#jvms-2.5&quot;&gt;&quot;JVMS 2.5 - Run-Time Data Areas&quot;&lt;&#x2F;a&gt;, Java Virtual Machine Specification SE 25 &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;전체 코드는 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;YangSiJun528&#x2F;3c4210f0709e19ac72070c62a6b7333c&quot;&gt;Gist에 올려두었다&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;specs&#x2F;jvms&#x2F;se25&#x2F;html&#x2F;jvms-6.html#jvms-6.5&quot;&gt;&quot;JVMS 6.5 - Instructions&quot;&lt;&#x2F;a&gt;, Java Virtual Machine Specification SE 25 &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;OpenJDK, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openjdk&#x2F;jdk&#x2F;blob&#x2F;master&#x2F;src&#x2F;hotspot&#x2F;share&#x2F;oops&#x2F;objArrayOop.hpp&quot;&gt;&quot;objArrayOop.hpp&quot;&lt;&#x2F;a&gt; 및 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openjdk&#x2F;jdk&#x2F;blob&#x2F;master&#x2F;src&#x2F;hotspot&#x2F;share&#x2F;oops&#x2F;objArrayOop.inline.hpp&quot;&gt;&quot;objArrayOop.inline.hpp&quot;&lt;&#x2F;a&gt;, GitHub &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;코드에서 &lt;code&gt;oop&lt;&#x2F;code&gt;는 Ordinary Object Pointer의 약자로, &quot;일반적인 객체를 가리키는 포인터&quot;라는 뜻이다. OpenJDK 코드에는 이 설명이 없어서 OpenJDK 개발자였던 Aleksey Shipilëv의 블로그에서 의미를 확인했다. Aleksey Shipilëv, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shipilev.net&#x2F;jvm&#x2F;anatomy-quarks&#x2F;23-compressed-references&#x2F;#_compressed_references&quot;&gt;&quot;JVM Anatomy Quarks #23: Compressed References&quot;&lt;&#x2F;a&gt; 및 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shipilev.net&#x2F;jvm&#x2F;objects-inside-out&#x2F;&quot;&gt;&quot;Java Objects Inside Out&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;다양한 JDK 종류의 차이를 알아보려면 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;whichjdk.com&#x2F;&quot;&gt;Which Version of JDK Should I Use?&lt;&#x2F;a&gt;를 참고하자. &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;InfoQ, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.infoq.com&#x2F;presentations&#x2F;netflix-java&#x2F;&quot;&gt;&quot;Netflix Adopts Java 17&quot;&lt;&#x2F;a&gt;, InfoQ Presentations &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-9&quot;&gt;
&lt;p&gt;Stack Overflow, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;2397984&#x2F;undefined-unspecified-and-implementation-defined-behavior&quot;&gt;&quot;Undefined, unspecified and implementation-defined behavior&quot;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-9-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-10&quot;&gt;
&lt;p&gt;Oracle, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.graalvm.org&#x2F;latest&#x2F;reference-manual&#x2F;native-image&#x2F;&quot;&gt;&quot;GraalVM Native Image&quot;&lt;&#x2F;a&gt;, GraalVM Documentation &lt;a href=&quot;#fr-10-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-11&quot;&gt;
&lt;p&gt;같은 소스코드라도 컴파일러, OS, 런타임에 따라 다른 결과물이 만들어진다. 그리고 컴파일러와 OS 자체도 프로그래밍 언어로 작성된 프로그램이므로 환경마다 구현이 다를 수 있다. &lt;a href=&quot;#fr-11-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-12&quot;&gt;
&lt;p&gt;개인적으로 이런 저수준 동작에 대한 호기심이 있었다. 이 과정에서 간단한 책을 보거나 토이 프로젝트를 진행했었다. 특히 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sourceacademy.org&#x2F;sicpjs&#x2F;&quot;&gt;SICP: JavaScript Edition&lt;&#x2F;a&gt;를 읽으며, 겉보기에는 동일한 언어라도 평가 전략이나 실행 모델과 같은 구현 선택에 따라 동작이 달라질 수 있다는 점이 인상 깊었다. 이런 관점에서 보면 Java 배열 인덱스 접근의 시간복잡도 또한 구현에 의해 결정될 가능성이 크다고 보았고, 이런 실제하는 예시를 통해서 언어의 명세와 구현을 구분하는 시야에 대해서 공유하고 싶었다. &lt;a href=&quot;#fr-12-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</description>
      </item>
      <item>
          <title>Nand to Tetris 강의 수강 후기: 컴퓨터의 근본 원리 이해하기</title>
          <pubDate>Tue, 11 Jun 2024 00:00:00 +0000</pubDate>
          <author>Sijun Yang</author>
          <link>https://sijun-yang.com/blog/nand-to-tetris/</link>
          <guid>https://sijun-yang.com/blog/nand-to-tetris/</guid>
          <description xml:base="https://sijun-yang.com/blog/nand-to-tetris/">&lt;p&gt;몇 달 전에, Nand to Tetris 라는 강의를 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;chijoon-study&#x2F;cs-study&#x2F;wiki&#x2F;Nand2Tetris-%EC%96%91%EC%8B%9C%EC%A4%80&quot;&gt;수강&lt;&#x2F;a&gt; 완료했다. 간단한 소개와 느낀점에 대해 공유해보고자 한다.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;teachyourselfcs.com&#x2F;&quot;&gt;Teach Yourself Computer Science&lt;&#x2F;a&gt;라는 인터넷에서 혼자서 CS를 학습하기 위한 커리큘럼을 소개해주는 사이트에 추천해줘서 수강하게 되었다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nand-to-tetris-sogae&quot;&gt;Nand to Tetris 소개&lt;&#x2F;h2&gt;
&lt;p&gt;시몬 쇼켄(Simon Schocken) 및 노암 니산(Noam Nisan)이 만들었다.
컴퓨터의 작동원리를 실습을 통해 이해할 수 있는 프로젝트이다.
간단한 논리 연산자인 Nand부터 시작해서 GUI 프로그램을 동작시킬 수 있는 범용 컴퓨터를 만든다.
하드웨어 및 소프트웨어를 순서대로 만들어 보면서 컴퓨터 과학의 주요 지식을 이해할 수 있다.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jinhaeng-junbimul&quot;&gt;진행 준비물&lt;&#x2F;h3&gt;
&lt;p&gt;The Elements of Computing Systems(한국어 번역본: 밑바닥부터 만드는 컴퓨팅 시스템)이라는 도서와 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.coursera.org&#x2F;courses?query=from%20nand%20to%20tetris&quot;&gt;Coursera&lt;&#x2F;a&gt;에 있는 강의를 함께 들어가면서 진행했다. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@MakkuZjAileron&#x2F;playlists&quot;&gt;강의는 유튜브로도 공개되어 있다.&lt;&#x2F;a&gt;)
나는 &lt;em&gt;밑바닥부터 만드는 컴퓨팅 시스템&lt;&#x2F;em&gt; 과  Coursera 강의를 함꼐 수강하였다.
Coursera에서 실습 과제를 제출하고 평가받을 수 있어 학습에 도움을 준다.
강의나 책 중 하나만 보아도 문제는 없어 보이지만, 둘 다 함께 보는 것을 추천한다.
( Coursera의 강의를 전부 수료하면 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;%EC%8B%9C%EC%A4%80-%EC%96%91-31a91827b&#x2F;details&#x2F;certifications&#x2F;&quot;&gt;수료증&lt;&#x2F;a&gt;도 준다. )&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neugginjeom&quot;&gt;느낀점&lt;&#x2F;h2&gt;
&lt;h4 id=&quot;keompyuteoyi-gibon-weonri-ihae&quot;&gt;컴퓨터의 기본 원리 이해&lt;&#x2F;h4&gt;
&lt;p&gt;강의를 통해 고수준 언어를 컴파일하면서 C++이나 Java에서 다루는 객체지향이 내부적으로 함수와 구조체로 구성된다는 것을 깨달았다.
저수준 언어에서는 명령어를 위에서부터 아래로 순차적으로 실행하며, 가끔 Jump하면서 함수나 분기, 반복문을 구현한다.
CPU와 RAM은 논리 게이트의 집합으로 구성되며, (기본적인) CPU는 생각보다 단순한 역할을 수행한다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;peurogeuraeminge-daehan-deo-yeolrin-sago&quot;&gt;프로그래밍에 대한 더 열린 사고&lt;&#x2F;h4&gt;
&lt;p&gt;모든 프로그래밍 언어는 결국 기계어로 수행된다는 사실을 깨달았다.
각 언어는 해결하고자 하는 문제나 특화된 부분이 다를 수 있지만, 결국 기계어 입장에서는 동일하게 수행된다.
이 사실을 알고 나서, 새로운 것을 받아들이는 데 더 열린 자세를 갖게 되었다.
나는 잘 모르는 분야나 한 번도 해본 적 없는 것들에 대한 묘한 두려움이 있었다.
특히 나에게 익숙한 Java와 Spring을 주로 사용하고, 다른 기술에 대해서는 폐쇄적인 태도를 가지고 있었다.
하지만 열린 사고를 가진 지금은 NodeJS 기반의 서버 개발이나 프론트엔드 개발에도 관심을 가지고 있고,
기존에 사용해보지 않는 기술 스택을 사용해서 토이 프로젝트 개발을 기획하고 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;silseubyi-jungyoseong&quot;&gt;실습의 중요성&lt;&#x2F;h4&gt;
&lt;p&gt;강의에서 다루는 많은 내용을 알고는 있었지만, 실제로 이해하지 못하고 있었다는 것을 깨달았다.
단순히 아는 것과 이해하는 것은 다르며, 직접 결과물을 만들어보는 것을 통해 더 잘 이해할 수 있었다.&lt;&#x2F;p&gt;
&lt;p&gt;그래서 자료구조를 더 이해하기 위해 C 언어를 배워서 직접 자료구조를 구현해보고 있다.
이후에는 소켓 네트워크 구현과 같이 CS의 기초적인 부분을 실습해보고 싶다.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aswiun-jeom&quot;&gt;아쉬운 점&lt;&#x2F;h2&gt;
&lt;p&gt;개인적으로 프로젝트를 진행하면서 아쉬운 점은 다음과 같다.
특히 프로젝트의 구현과 실제 구현이 차이가 있는건 납득 가능한 부분이지만, 실제 구현과 비교하지 않는 것은 아쉽다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;inteoreobteue-daehan-seolmyeong-bujae&quot;&gt;인터럽트에 대한 설명 부재&lt;&#x2F;h4&gt;
&lt;p&gt;프로젝트에서 만드는 CPU에서 인터럽트 자체가 없어서 실제 OS나 컴퓨터를 이해하는데 중요한 인터럽트의 설명이 누락되어 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ose-daehan-seolmyeong-bujog&quot;&gt;OS에 대한 설명 부족&lt;&#x2F;h4&gt;
&lt;p&gt;강의는 컴퓨팅 시스템에 대한 이해를 중점으로 한다.
리눅스처럼 현대 OS의 동작을 기대했다면 실망할 수 있다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2bu-silseub-nanido-yeoryeoum&quot;&gt;2부 실습 난이도 여려움&lt;&#x2F;h4&gt;
&lt;p&gt;강의의 2부로 넘어가면서 난이도가 급격히 올라갔다는 느낌을 받았다.
1부까지는 외부 자료를 거의 참고하지 않고 구현할 수 있었는데, 2부 넘어가고부터 내 실력으론 구글링 없이는 문제 해결이 불가능했다.
복잡한 요구사항을 구현해본 경험이 적은 사람에게는 어려울 수 있을 것 같다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;silje-guhyeone-daehan-bigyo-bujog&quot;&gt;실제 구현에 대한 비교 부족&lt;&#x2F;h4&gt;
&lt;p&gt;강의에서 다룬 내용이 실제 구현과 어떤 차이가 있는지 설명해주지 않아 아쉬웠다.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;hangugeo-beonyeog-munje&quot;&gt;한국어 번역 문제&lt;&#x2F;h4&gt;
&lt;p&gt;심각한 부분은 아니지만, 종종 오타&#x2F;오역이 보인다. 원서를 무리없이 읽을 수 있다면, 원서를 보고 진행하는 걸 추천한다. (여타 책들이 다 그렇겠지만)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mamuri&quot;&gt;마무리&lt;&#x2F;h2&gt;
&lt;p&gt;Nand to Tetris 강의를 통해 컴퓨터 시스템, 특히 컴퓨터와 프로그래밍 언어의 동작 원리를 이해할 수 있는 귀중한 경험이였다.
실습을 통해 이론적 지식을 실제로 구현해 보면서 얻은 인사이트는 다른 학습 방법으로 대체할 수 없다고 생각한다.
특히, 새로운 기술에 대한 열린 자세와 프로그래밍에 대한 더 넓은 시각을 얻은게 된 것이 나에게 중요한 성취 중 하나였다.
앞으로는 다양한 분야와 기술에 도전하며, 배운 내용을 바탕으로 더욱 성장해 나갈 것이다.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
