<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>공공돌</title>
    <link>https://sheep1sik.tistory.com/</link>
    <description>성장하는 공공돌 블로그   </description>
    <language>ko</language>
    <pubDate>Thu, 16 Apr 2026 08:52:43 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Sheep1sik</managingEditor>
    <image>
      <title>공공돌</title>
      <url>https://tistory1.daumcdn.net/tistory/5717627/attach/28543049de7e4ace99d8f4ace0d27bb4</url>
      <link>https://sheep1sik.tistory.com</link>
    </image>
    <item>
      <title>[ Claude ] 나만의 오케스트레이터 설계, 왜 직접 만들었고, 6개 팀은 어떻게 탄생했는가</title>
      <link>https://sheep1sik.tistory.com/190</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&quot;이미 하네스를 자동으로 만들어주는 플러그인이 있는데, 왜 직접 만들어?&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;답은 간단하다. &lt;b&gt;원리를 이해하고 싶었고, 나에게 맞는 것을 만들고 싶었다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 플러그인은 훌륭한 도구다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;하네스 구성해줘&quot;라고 말하면 도메인을 분석하고, 아키텍처 패턴을 선택하고, 에이전트와 스킬을 자동으로 생성해준다. 하지만 나는 그 과정을 &lt;b&gt;블랙박스로 넘기고 싶지 않았다&lt;/b&gt;.&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프레임워크를 쓰기 전에 프레임워크가 해결하는 문제를 직접 겪어봐야 한다는 말이 있다. UIKit을 이해하지 못한 채 SwiftUI를 쓰면, 문제가 생겼을 때 어디를 봐야 하는지 모른다. 하네스도 마찬가지다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md에 규칙을 적으면 AI가 왜 그 규칙을 따르는지, 에이전트를 분리하면 어떤 이점이 생기고 어떤 트레이드오프가 있는지, 스킬의 워크플로우를 어떻게 설계해야 AI가 일관되게 따르는지 이런 것들을 &lt;b&gt;직접 부딪히면서 이해하고 싶었다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그리고 무엇보다, 나는 iOS 개발자로서 &lt;b&gt;나만의 개발 습관과 작업 방식&lt;/b&gt;이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트를 동시에 운영하면서 쌓아온 나름의 원칙들이 있고, 트러블슈팅을 노션에 기록하는 습관이 있고, Apple 공식 문서를 우선 참고하는 버릇이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;범용 도구가 이 모든 걸 알아서 반영해줄 거라고 기대하기보다, &lt;b&gt;처음부터 내 방식으로 설계하는 게 더 확실&lt;/b&gt;했다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설계의 출발점: 무엇이 문제였는가&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;매번 반복되는 컨텍스트 설명&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code를 본격적으로 개발에 활용하기 시작하면서 가장 먼저 느낀 불편함은, &lt;b&gt;매 대화마다 같은 맥락을 반복 설명해야 한다&lt;/b&gt;는 것이었다. 1탄에서도 언급했지만, 이건 실제로 겪어보면 생각 이상으로 피로하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;이 프로젝트는 UIKit 기반이야&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;아키텍처는 MVVM-C 패턴이야&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;기존 코드 스타일을 따라줘&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;Codable 대신 Encodable/Decodable 분리해서 써&quot;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이걸 매번 말해주지 않으면? Claude는 SwiftUI 코드를 제안하거나, 기존 구조와 전혀 다른 패턴을 권하거나, 심지어 기존 코드를 &quot;더 좋게&quot; 만든다며 통째로 재작성하기도 했다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트 간 컨텍스트 혼선&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;iOS 프로젝트를 동시에 운영하다 보니 더 심각한 문제가 있었다. A 프로젝트에서 작업하다가 B 프로젝트로 넘어갔을 때, &lt;b&gt;이전 프로젝트의 맥락이 섞여 들어오는&lt;/b&gt; 경우가 있었다. 각 프로젝트마다 아키텍처도 다르고, 코드 스타일도 다르고, 사용하는 라이브러리도 다른데, AI가 이걸 제대로 구분하지 못하면 미묘한 불일치가 생긴다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;일회성 작업의 반복&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅을 할 때마다 같은 패턴이 반복됐다. 에러를 분석하고, 원인을 찾고, 해결하고 &amp;mdash; 여기까지는 좋다. 문제는 이 과정이 &lt;b&gt;다음에 비슷한 에러가 나면 처음부터 다시 시작&lt;/b&gt;된다는 것이었다. 기록이 체계적으로 남지 않으니, 3개월 전에 같은 에러를 어떻게 해결했는지 찾을 수가 없었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 세 가지 문제를 한꺼번에 해결하기 위해, 나는 &lt;b&gt;오케스트레이터&lt;/b&gt;를 설계하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터란 무엇인가&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터의 역할을 한 문장으로 정의하면 이렇다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;모든 작업을 직접 한 번에 처리하는 것이 아니라, 요청의 성격을 분석해 필요한 전문 팀에만 작업을 위임하고, 그 결과를 통합하는 것.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트라의 지휘자를 생각하면 된다. 지휘자는 바이올린을 직접 연주하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;어떤 파트가 언제 들어와야 하는지 판단하고, 전체적인 조화를 만든다. 내 오케스트레이터도 마찬가지다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요청이 들어오면 &lt;b&gt;성격을 파악&lt;/b&gt;한다 &amp;mdash; 이건 구현인가? 기획인가? 버그인가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;필요한 &lt;b&gt;전문 팀만 선택적으로 호출&lt;/b&gt;한다 &amp;mdash; 모든 팀을 매번 다 부르지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;각 팀의 결과를 &lt;b&gt;통합해서 사용자에게 전달&lt;/b&gt;한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;핵심은 &quot;선택적 호출&quot;이다. 변수명 하나 바꾸는데 아키텍처 분석 팀까지 동원하면, 그건 체계가 아니라 관료주의다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;최상위 원칙 설계: 오케스트레이터의 헌법&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀을 설계하기 전에, 전체를 관통하는 원칙부터 세워야 했다. 이 원칙들은 CLAUDE.md의 최상단에 위치하며, 모든 팀의 작업을 제어하는 &lt;b&gt;헌법&lt;/b&gt; 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실전에서 부딪히면서 정리한 10가지 원칙은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; width: 40px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;#&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;원칙&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 원칙이 없으면 생기는 문제&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;모든 요청에 모든 팀을 동시에 호출하지 않는다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;컨텍스트 낭비. 단순 수정에 6개 팀이 동원된다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요청의 성격을 먼저 분류하고, 필요한 팀만 선택 호출한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;모든 작업에 풀 프로세스가 적용되어 느려진다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 디자인, 코드, 아키텍처, 네이밍, 작업 흐름을 최대한 보존한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI가 &quot;더 좋은 방법&quot;이라며 기존 코드를 전면 재작성한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;새로운 제안은 현재 프로젝트 컨텍스트 안에서 검토한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;일반적 베스트 프랙티스가 프로젝트 일관성을 깨뜨린다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트별 프롬프트가 있다면 반드시 이를 우선 참고한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트 간 규칙이 혼선된다 (A 프로젝트 규칙이 B에 적용)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작업 결과는 재사용 가능한 개발 자산이 되도록 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;매번 같은 문제를 처음부터 다시 해결한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;7&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Apple Developer Documentation을 우선 참고 기준으로 삼는다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;블로그 글의 outdated 코드나 비권장 패턴이 적용된다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;8&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;참고 자료는 링크와 함께 왜 참고했는지 요약한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;근거 없는 제안이 들어오고, 나중에 판단 과정을 추적할 수 없다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;9&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Apple 공식 방향성과 충돌하는 해결책은 지양한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;deprecated API나 비권장 패턴이 슬며시 코드에 들어온다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;10&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;일반적 베스트 프랙티스를 강요하지 말고, 현재 프로젝트의 맥락을 우선 존중한다&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;TCA 프로젝트에 &quot;MVVM이 정석&quot;이라며 구조를 권한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 10가지 중 가장 자주 효과를 발휘하는 건 &lt;b&gt;3번과 10번&lt;/b&gt;이다. AI는 기본적으로 &quot;더 좋은 코드&quot;를 만들려 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그 의도는 좋지만, &lt;b&gt;&quot;더 좋은&quot;의 기준이 일반론인지 현재 프로젝트의 맥락인지&lt;/b&gt;에 따라 결과가 완전히 달라진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 원칙들이 없으면, Claude는 UIKit 프로젝트에서 SwiftUI를 권하고, SnapKit으로 통일된 프로젝트에서 Auto Layout을 제안한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 자산 보호: 하네스에서 가장 중요한 방어선&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;최상위 원칙 중에서도 별도 섹션으로 분리할 만큼 중요하게 다룬 것이 &lt;b&gt;기존 자산 보호&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI 에이전트에게 지시하지 않으면, 기존 코드를 &quot;개선&quot;하려 한다. 변수명을 바꾸고, 함수를 분리하고, 더 &quot;깔끔한&quot; 구조로 리팩토링한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제는 이게 &lt;b&gt;요청하지 않은 변경&lt;/b&gt;이라는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;버그 하나 고치려고 했는데 파일 3개가 바뀌어 있으면, 리뷰 범위가 넓어지고 의도치 않은 사이드 이펙트가 생길 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그래서 다음과 같은 방어선을 명시적으로 정의했다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 코드를 함부로 대체하거나 전면 재작성하지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 UI/디자인 시스템을 함부로 변경하지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 아키텍처와 일관성을 우선 고려한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;변경은 &lt;b&gt;최소 침습적(minimally invasive)&lt;/b&gt; 방식으로 제안한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구조 변경이 필요한 경우, 먼저 이유, 영향 범위, 대안, 리스크를 설명한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;더 좋아 보이는 방법이 있더라도, 프로젝트의 일관성을 해치면 신중히 제안한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그리고 해결책을 제시할 때는 &lt;b&gt;3단계로 나누어&lt;/b&gt; 개발자가 상황에 맞는 수준을 선택할 수 있게 했다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단계&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설명&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;적용 시점&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;가장 작은 수정안&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 구조를 전혀 건드리지 않고 최소한의 변경&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;급한 핫픽스, 배포 직전&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;권장 개선안&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 구조 안에서 더 안전한 패턴으로 개선&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;일반적인 스프린트 작업&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;장기적 리팩토링안&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구조적 변경이 수반되지만 근본적으로 해결&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기술 부채 정리 기간&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;옳은 것과 적절한 것은 다르다. SwiftUI가 미래의 방향이라 해도, UIKit으로 80% 완성된 프로젝트에서 화면 하나를 SwiftUI로 만들면 그건 개선이 아니라 혼란이다. 이 구분을 AI에게 가르치는 것이 기존 자산 보호의 핵심이다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6개 팀 설계: 어떤 역할이 필요한가&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터의 핵심은 팀이다. iOS 개발 과정에서 반복적으로 필요한 역할들을 분석해서 &lt;b&gt;6개 전문 팀&lt;/b&gt;으로 나눴다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 구성의 원칙: 왜 모든 팀이 4명인가&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;모든 팀은 &lt;b&gt;4명의 역할&lt;/b&gt;로 구성된다. 이건 임의로 정한 숫자가 아니라, 소프트웨어 개발의 기본 사이클을 반영한 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기능&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 역할이 없으면&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;리드 (방향 설정)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제를 해석하고 작업 방향을 결정&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;목표 없이 작업이 흩어진다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;실행/분석 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제 작업 수행 또는 분석&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;결정만 있고 실행이 없다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;검토 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;품질 점검, 영향 범위 확인, 사이드 이펙트 탐지&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실행 결과의 부작용을 놓친다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기록, 정리, 재사용 가능한 자산화&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같은 문제를 다음에 또 처음부터 해결한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단일 관점으로 결론을 내면 특정 측면이 빠진다. 구현만 생각하면 리뷰가 빠지고, 분석만 하면 문서화가 빠진다. 4명 구조는 이런 &lt;b&gt;관점의 누락을 구조적으로 방지&lt;/b&gt;하기 위한 장치다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다만 매번 4명의 관점을 장황하게 펼칠 필요는 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;작은 작업에서는 내부 협업 결과만 간단히 통합&lt;/b&gt;해서 제시하고, 큰 작업에서만 각 역할의 관점을 분명히 드러낸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 내부에서 의견 차이가 있다면 무리하게 하나로 합치지 않고, 주요 선택지와 판단 근거를 함께 정리해서 개발자가 최종 결정을 내릴 수 있게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 1: 개발 팀 &amp;mdash; 가장 자주 호출되는 팀&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코드를 직접 만지는 모든 작업이 이 팀을 거친다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #e8f4e8;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;개발 리드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제를 해석하고 구현 방향을 결정한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;구현 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제 코드 수정, 기능 구현, 구조 반영을 수행한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;리뷰 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 코드와의 충돌, 영향 범위, 사이드 이펙트, 품질을 점검한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;변경 내용, 적용 포인트, 주의점, 후속 작업을 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;왜 리뷰 담당이 개발 팀 안에 있는가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;별도의 리뷰 프로세스를 거치기 전에, &lt;b&gt;구현 단계에서부터 기존 코드와의 충돌을 1차로 점검&lt;/b&gt;하기 위해서다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;외과 수술에서 집도의와 별개로 수술실 내 확인 간호사가 있는 것과 같은 원리다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 2: 기획 팀 &amp;mdash; 범위 정의가 먼저&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요구사항이 모호하거나 기능의 범위를 먼저 잡아야 할 때 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #e8e8f4;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기획 리드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요구사항과 기능 목적을 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;플로우 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;유저 플로우와 화면 흐름을 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;검증 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;범위 과다, 모호성, 빠진 요구사항을 점검한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기획안, 결정 사항, 우선순위를 문서화한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;프로필 화면에 뱃지 시스템 추가해줘&quot;라는 요청이 들어왔다고 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;바로 코드를 쓰면 안 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;뱃지는 어떤 조건에서 획득하는지? 화면 어디에 보여주는지? 서버 API가 필요한지? &lt;b&gt;기획 팀이 이 정리를 먼저 하고, 정리된 결과를 개발 팀에 넘긴다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 3: 인사이트 팀 &amp;mdash; 학습과 기록의 선순환&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;새로운 기술이나 패턴을 학습할 때, 또는 &quot;이 API는 어떻게 쓰는 게 맞아?&quot;라는 질문에 답할 때 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f4e8e8;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;공식 문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Apple Developer Documentation, WWDC, 공식 샘플 코드 중심으로 조사한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;실무 적용 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 프로젝트에 실제로 어떻게 적용할지 분석한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;비교 분석 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다른 기술, 패턴, 접근 방식과의 차이점과 트레이드오프를 비교한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;인사이트를 노션에 바로 붙여넣을 수 있게 정리하고 참고 링크를 포함한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 팀의 핵심은 &lt;b&gt;&quot;조사 &amp;rarr; 적용 &amp;rarr; 기록&quot;의 사이클&lt;/b&gt;이다. 단순히 &quot;이건 이래요&quot;가 아니라, &quot;이건 이렇고, 우리 프로젝트에는 이런 상황에서 적용하면 되고, 주의할 점은 이거&quot;까지 한 번에 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그리고 이 결과가 노션에 기록되어 팀 지식이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;iOS 개발에서 이 팀이 특히 중요한 이유는 &lt;b&gt;Apple 공식 문서 우선 참고&lt;/b&gt; 원칙 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI가 블로그 글이나 Stack Overflow 답변을 기반으로 설명하면, deprecated API를 권하거나 outdated된 패턴을 제안할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공식 문서 담당이 이걸 1차로 필터링한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 4: 트러블슈팅 작성 팀 &amp;mdash; 같은 문제를 두 번 풀지 않기 위해&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에러나 버그를 해결한 후, 그 과정을 체계적으로 기록하는 팀이다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f4f4e8;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문제 분석 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에러 현상, 재현 조건, 문제 상황을 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;원인 추적 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;근본 원인(root cause)을 분석한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;해결 검토 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;해결안, 대안, 재발 방지 포인트를 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅 노션 템플릿에 맞게 구조화한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기록 양식을 통일해 놓은 것이 핵심이다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;제목&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 상황&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;원인 분석&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;해결 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;왜 이 해결이 적절한지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;대안과 비교&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;재발 방지 포인트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;참고 자료 링크&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;관련 키워드 태그&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 양식을 따르면 3개월 후에 비슷한 에러가 발생했을 때, &lt;b&gt;노션에서 키워드 검색만으로 과거 해결 과정을 즉시 찾을 수 있다&lt;/b&gt;. 앞서 말한 &quot;일회성 작업의 반복&quot; 문제를 이 팀이 해결한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 5: 아키텍처 분석 팀 &amp;mdash; 가장 무거운 팀&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;새로운 기술 도입, 구조 변경, 아키텍처 결정이 필요할 때 호출된다. 신중하게 호출해야 하는 팀이다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #e8f4f4;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;아키텍처 리드&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;후보 구조와 판단 기준을 정의한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;프로젝트 적합성 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 프로젝트 특성과 제약조건을 분석한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;비교 검토 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다른 아키텍처와의 차이점, 장단점, 복잡도, 리스크를 비교한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;ADR(Architecture Decision Record) 형태로 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 팀의 특징은 결론만 내리지 않는다는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;반드시 &lt;b&gt;후보들의 장단점, 프로젝트 제약조건, 선택 이유, 제외 이유, 리스크&lt;/b&gt;를 함께 정리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예를 들어 &quot;MVVM-C를 채택합니다&quot;로 끝나지 않는다. &quot;MVVM-C를 채택합니다. TCA도 고려했지만 학습 곡선과 현재 프로젝트 규모를 감안하면 MVVM-C가 더 적절합니다. 다만 상태 관리가 복잡해지면 부분적으로 TCA 도입을 재검토할 필요가 있습니다&quot;까지 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 6: 프로젝트 검수 팀 &amp;mdash; 배포 전 마지막 관문&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;배포 전 안정성 점검이나 성능 최적화 검토 시 호출된다. 코드를 직접 수정하지 않고, &lt;b&gt;진단과 권장사항만 제시&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f4e8f4;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;책임&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;품질 검수 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기능 완성도와 에러 가능성을 점검한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;성능 검수 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;메모리, 렌더링, 동시성, 최적화 포인트를 점검한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;일관성 검수 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 코드 스타일, 디자인, 구조 훼손 여부를 검토한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;문서 담당&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;검수 결과, 수정 권장사항, 체크리스트를 정리한다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;검수 결과는 &lt;b&gt;&quot;바로 수정 가능한 포인트&quot;와 &quot;장기 개선 포인트&quot;를 구분&lt;/b&gt;해서 정리한다. 배포 전에 반드시 고쳐야 할 것과, 다음 스프린트에서 개선해도 되는 것을 명확히 나누는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6개 팀 전체 구조&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6개 팀을 한눈에 보면 이렇다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot; style=&quot;background-color: #f8f8f8; padding: 20px; border-radius: 8px; overflow-x: auto; font-size: 13px; line-height: 1.6;&quot;&gt;&lt;code&gt;                     ┌──────────────────────┐
                     │    오케스트레이터      │
                     │   (요청 분류 &amp;amp; 통합)   │
                     └──────────┬───────────┘
                                │
         ┌──────────────────────┼──────────────────────┐
         │                      │                      │
    ┌────┴────┐           ┌────┴────┐           ┌────┴────┐
    │ 개발 팀  │           │ 기획 팀  │           │인사이트팀│
    │         │           │         │           │         │
    │ 리드    │           │ 리드    │           │ 공식문서 │
    │ 구현    │           │ 플로우  │           │ 실무적용 │
    │ 리뷰    │           │ 검증    │           │ 비교분석 │
    │ 문서    │           │ 문서    │           │ 문서    │
    └─────────┘           └─────────┘           └─────────┘

    ┌─────────┐           ┌─────────┐           ┌─────────┐
    │트러블슈팅│           │아키텍처 │           │프로젝트 │
    │ 작성 팀  │           │ 분석 팀  │           │ 검수 팀  │
    │         │           │         │           │         │
    │ 문제분석 │           │ 리드    │           │ 품질    │
    │ 원인추적 │           │ 적합성  │           │ 성능    │
    │ 해결검토 │           │ 비교검토 │           │ 일관성  │
    │ 문서    │           │ 문서    │           │ 문서    │
    └─────────┘           └─────────┘           └─────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 호출 규칙: 과잉 대응을 방지하는 핵심 로직&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6개 팀을 만들어놓고 매번 다 부르면 의미가 없다. &lt;b&gt;요청의 성격에 따라 필요한 팀만 골라 쓰는 규칙&lt;/b&gt;이 오케스트레이터의 핵심 로직이다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요청 유형&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;호출 팀&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이유&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;간단한 구현 요청&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;개발 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코드만 수정하면 되므로 다른 팀 불필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;요구사항이 모호한 기능 요청&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기획 팀 &amp;rarr; 개발 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;범위 정의 후 구현. 순서가 중요하다&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에러/버그 해결&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;개발 팀 + 트러블슈팅 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;수정과 기록을 동시에 진행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;새로운 기술/패턴 학습&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;인사이트 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;조사와 정리만 필요하므로 개발 팀 불필요&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기술 도입/구조 변경 검토&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;아키텍처 팀 + 인사이트 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구조 분석과 기술 조사를 병행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;배포 전 안정성 점검&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;프로젝트 검수 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코드 수정 없이 진단만 수행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;큰 구조 변경이 포함된 요청&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기획 팀 + 아키텍처 팀 + 개발 팀&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;범위 정의 &amp;rarr; 구조 설계 &amp;rarr; 구현의 풀 사이클&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;추가 규칙이 하나 더 있다: &lt;b&gt;기록 가치가 있는 문제나 학습 내용이 나오면, 해당 작업 후 문서화 팀을 추가 호출&lt;/b&gt;한다. 트러블슈팅이 될 수도 있고, 인사이트가 될 수도 있다. 이 판단은 오케스트레이터가 자동으로 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비효율 경고 시스템: 과잉 프로세스 방지 장치&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;체계적인 시스템을 만들면 생기는 부작용이 있다. &lt;b&gt;과잉 프로세스&lt;/b&gt;다. 변수명 하나 바꾸는데 6개 팀이 동원되고 ADR이 작성되면, 그건 체계가 아니라 관료주의다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI에게 &quot;과잉 대응하지 마&quot;라고 명시적으로 알려주지 않으면, 기본적으로 가장 무거운 프로세스를 적용하려 한다. 이 문제를 해결하기 위해 &lt;b&gt;비효율 경고 레벨&lt;/b&gt;을 설계했다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; width: 80px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;레벨&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;상태&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터의 행동&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; color: green;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Level 1&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 방식이 적절함&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그대로 진행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; color: #cc9900;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Level 2&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;약간 비효율적이지만 진행 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;진행하되 참고 수준으로 언급&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; color: orange;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Level 3&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 호출이나 작업 범위를 줄이는 것이 좋음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;더 가벼운 워크플로우를 제안&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; color: red;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Level 4&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 방식은 과도함&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;더 단순한 워크플로우로 전환 권장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비효율을 감지하면 단순히 &quot;비효율적입니다&quot;로 끝나지 않는다. 반드시 다음을 함께 보고하도록 설계했다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;어떤 부분이 비효율적인지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;왜 비효율적인지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 단계에서 더 적절한 대안은 무엇인지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;생략하거나 통합할 수 있는 팀 또는 작업은 무엇인지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;속도와 품질을 균형 있게 유지하는 추천 작업 방식&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설계 의도: 이 시스템의 핵심은 &quot;AI가 스스로 자기 프로세스를 점검하게 만드는 것&quot;이다. 사람이 매번 &quot;이건 너무 과하다&quot;라고 지적하는 대신, 오케스트레이터 자체에 자기 점검 메커니즘을 내장시켰다. 실제로 사용하다 보면 오케스트레이터가 &quot;이 작업은 Level 3입니다. 인사이트 팀 없이 개발 팀만으로 충분합니다&quot;라고 스스로 판단하는 경우가 생긴다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작업 흐름: 7단계 파이프라인&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터가 요청을 받으면 항상 다음 순서로 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;gradle&quot; style=&quot;background-color: #f8f8f8; padding: 20px; border-radius: 8px; overflow-x: auto; font-size: 14px; line-height: 1.8;&quot;&gt;&lt;code&gt;Step 1  요청의 성격을 파악한다
           &amp;darr;
Step 2  이 요청이 어떤 팀의 작업인지 분류한다
           &amp;darr;
Step 3  필요한 팀만 호출한다
           &amp;darr;
Step 4  기존 프로젝트 프롬프트와 충돌하는지 확인한다
           &amp;darr;
Step 5  기존 코드/디자인/구조를 해치지 않는 방향으로 해결책을 만든다
           &amp;darr;
Step 6  필요하면 참고 자료와 근거를 함께 정리한다
           &amp;darr;
Step 7  기록 가치가 있는 경우 노션용 형식으로 정리한다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Step 4&lt;/b&gt;가 특히 중요하다. 4개의 프로젝트를 동시에 운영하다 보면, A 프로젝트의 규칙이 B 프로젝트에 섞여 들어갈 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트별 CLAUDE.md가 존재하면 글로벌 규칙보다 이것이 우선한다는 것을 명시적으로 확인하는 단계다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Step 7&lt;/b&gt;도 눈에 띄는 단계다. 매 작업이 끝날 때 &quot;이 작업에서 기록할 만한 것이 있는가?&quot;를 자동으로 판단한다. 있다면 트러블슈팅 양식이나 인사이트 양식으로 정리하고, 노션 MCP를 통해 자동 기록한다. 이 단계 덕분에 &lt;b&gt;작업이 곧 기록&lt;/b&gt;이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;멀티 프로젝트 운영: 글로벌과 프로젝트의 분리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4개 프로젝트를 동시에 운영하면서 가장 신경 쓴 부분이 &lt;b&gt;컨텍스트 분리&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;계층&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위치&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;담당 내용&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;글로벌 CLAUDE.md&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6개 팀 구성, 최상위 원칙, 팀 호출 규칙, 비효율 경고, 기록 규칙, 출력 프로토콜&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;프로젝트 CLAUDE.md&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;./CLAUDE.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 팀(10명), 스킬(11개), 파이프라인 규칙, 기술 스택, 디자인 토큰&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글로벌 CLAUDE.md에는 &quot;어떤 팀이 있고, 어떤 원칙을 따르는가&quot;라는 &lt;b&gt;운영 체계&lt;/b&gt;가 들어간다. 프로젝트 CLAUDE.md에는 &quot;이 프로젝트는 어떤 기술 스택이고, 에이전트는 어떻게 동작하는가&quot;라는 &lt;b&gt;실행 규칙&lt;/b&gt;이 들어간다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 분리 덕분에 같은 오케스트레이터 원칙을 공유하면서도, 프로젝트마다 완전히 다른 환경에서 작업할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code의 CLAUDE.md는 override가 아니라 병합(concatenation)된다. 글로벌과 프로젝트 CLAUDE.md가 동시에 로드되면서, 나중에 읽힌 프로젝트 규칙이 더 높은 우선순위를 가진다. 이 메커니즘 덕분에 글로벌 원칙을 기본으로 깔되, 프로젝트별로 다른 세부 규칙을 적용하는 것이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;출력 프로토콜: 매번 같은 포맷으로&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오케스트레이터의 모든 출력은 다음 7가지를 포함하도록 규격화했다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;이번 요청의 성격&lt;/b&gt; &amp;mdash; &quot;이건 버그 수정 요청입니다&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;호출할 팀&lt;/b&gt; &amp;mdash; 어떤 팀이 투입되었는지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;왜 그 팀이 필요한지&lt;/b&gt; &amp;mdash; 팀 선택의 근거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;실제 해결 내용&lt;/b&gt; &amp;mdash; 작업 결과물&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기존 코드/디자인을 어떻게 보호했는지&lt;/b&gt; &amp;mdash; 기존 자산 보호 관점 리포트&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt; (필요 시) &amp;mdash; 링크와 참고 이유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;노션용 정리 내용&lt;/b&gt; (필요 시) &amp;mdash; 트러블슈팅/인사이트 기록 양식&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5번이 핵심이다. 매 작업마다 &lt;b&gt;&quot;기존 것을 어떻게 보호했는지&quot;를 명시적으로 보고&lt;/b&gt;하게 함으로써, AI가 의도치 않게 기존 코드를 훼손하는 것을 구조적으로 방지한다. 보고서에 이 항목이 빠져 있으면, 뭔가 빼먹은 거다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;노션 자동 기록: 지식 자산화의 마지막 퍼즐&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설계의 출발점에서 언급한 &quot;일회성 작업의 반복&quot; 문제, 그 해답이 노션 자동 기록이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;MCP(Model Context Protocol)를 통해 노션과 연동하고, 오케스트레이터가 기록이 필요하다고 판단하면 &lt;b&gt;노션 DB에 직접 페이지를 생성&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기록 프로세스&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;excel&quot; style=&quot;background-color: #f8f8f8; padding: 20px; border-radius: 8px; overflow-x: auto; font-size: 14px; line-height: 1.8;&quot;&gt;&lt;code&gt;작업 완료
    &amp;darr;
기록 대상인지 판단 (오케스트레이터 자동)
    &amp;darr;
&quot;노션에 기록할까요?&quot; 확인
    &amp;darr;
Notion MCP로 DB에 페이지 생성 + 본문 작성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅과 인사이트는 별도의 노션 DB로 분리 운영한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;각각의 속성(날짜, 상태, 유형, 프로젝트명)이 자동으로 채워지고, 본문은 앞서 정의한 표준 양식을 따른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용자가 &quot;기록해줘&quot;라고 명시적으로 요청하면 확인 없이 바로 기록한다. 매번 물어보는 것도 불필요한 오버헤드이기 때문에, 이런 세밀한 조건 분기도 설계에 포함시켰다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;대규모 변경 주의 원칙&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;마지막으로, 오케스트레이터에 하나 더 장치를 넣었다. 다음에 해당하는 작업은 &lt;b&gt;대규모 변경&lt;/b&gt;으로 간주한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;파일 구조 전면 변경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;아키텍처 교체&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;디자인 시스템 변경&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;외부 라이브러리 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;데이터 모델 대규모 수정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;대규모 변경이 감지되면 오케스트레이터는 바로 코드부터 쓰지 않는다. 먼저 영향 범위, 리스크, 대안, 기대 효과를 정리하고, &lt;b&gt;항상 가장 작은 수정으로 해결 가능한지 먼저 검토&lt;/b&gt;한다. 작은 수정으로 해결되지 않을 때만 구조 개선안을 제안한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이건 AI의 기본 성향을 제어하기 위한 장치다. Claude는 기본적으로 &quot;깔끔한 해결&quot;을 선호한다. 제어하지 않으면 작은 문제에도 큰 리팩토링을 시작하려 한다. &lt;b&gt;&quot;가장 작은 수정부터&quot;&lt;/b&gt;라는 원칙이 이걸 막아준다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;마치며&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 플러그인을 쓰지 않고 직접 만든 이유는 &quot;원리를 이해하고, 나에게 맞는 것을 만들기 위해서&quot;라고 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제로 직접 설계하면서 얻은 것을 정리하면 이렇다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;원리에 대한 이해&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md에 적은 규칙이 왜 지켜지고, 왜 가끔 안 지켜지는지 &amp;mdash; 문맥 길이와 규칙 준수율의 관계를 체감했다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트를 분리하는 것의 실질적 이점과 오버헤드 &amp;mdash; 무조건 나누는 게 좋은 건 아니라는 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI에게 &quot;하지 마&quot;를 가르치는 것이 &quot;해라&quot;를 가르치는 것보다 어렵다는 것&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;나에게 맞는 시스템&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4개 프로젝트의 컨텍스트 분리가 자연스럽게 작동한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅과 인사이트가 자동으로 노션에 쌓인다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Apple 공식 문서 우선 참고라는 내 습관이 시스템에 녹아들었다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비효율 경고 시스템 덕분에 과잉 프로세스에 시달리지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;물론 이 오케스트레이터도 완벽하지 않다. 약 260줄의 CLAUDE.md는 권장 200줄을 넘기고, 6개 팀의 4인 구조가 항상 최적인지는 더 실험이 필요하다. 하지만 &lt;b&gt;직접 만들었기 때문에 어디를 고쳐야 하는지 안다&lt;/b&gt;. 블랙박스를 쓰면 문제가 생겼을 때 어디를 봐야 하는지 모른다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Claude</category>
      <category>Claude</category>
      <category>claude code</category>
      <category>Harness</category>
      <category>IOS</category>
      <category>공공돌</category>
      <category>오케스트레이터 설계</category>
      <category>하네스</category>
      <category>하네스 엔지니어링</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/190</guid>
      <comments>https://sheep1sik.tistory.com/190#entry190comment</comments>
      <pubDate>Fri, 10 Apr 2026 15:44:45 +0900</pubDate>
    </item>
    <item>
      <title>[ Claude ] 하네스 엔지니어링이란 무엇인가?</title>
      <link>https://sheep1sik.tistory.com/189</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code를 쓰다 보면 한 가지 불편함을 느끼게 된다. 분명 똑똑한 도구인데, &lt;b&gt;매 대화마다 같은 맥락을 반복 설명해야 한다&lt;/b&gt;는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;나는 iOS 개발자고, 이 프로젝트는 UIKit 기반이고, 아키텍처는 이렇고, 코드 스타일은 저렇고...&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;매번 이걸 말해줘야 Claude가 프로젝트에 맞는 답을 준다. 안 그러면? 일반적인 베스트 프랙티스를 그대로 던져주거나, 내 프로젝트 컨텍스트와 동떨어진 제안을 한다. 코드를 통째로 재작성하거나, 기존 설계를 무시한 &quot;더 좋은&quot; 구조를 권하기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이건 Claude의 문제가 아니다. &lt;b&gt;구조의 부재&lt;/b&gt;가 문제다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;AI 에이전트에게 &quot;어떻게 일해야 하는지&quot;를 체계적으로 정의해주지 않으면, 매번 다른 방식으로 작동할 수밖에 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 문제를 해결하기 위해 AI 에이전트의 행동 체계를 설계하고 구축하는 접근법 &lt;b&gt;하네스 엔지니어링(Harness Engineering)&lt;/b&gt;에 대해 이야기하려 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스(Harness)란 무엇인가&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사전적 의미에서 출발하기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness의 사전적 의미는 &quot;마구(馬具)&quot; &amp;mdash; 말의 힘을 제어하고 원하는 방향으로 전달하는 장비다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;소프트웨어 세계에서도 같은 의미로 쓰인다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Test Harness&lt;/b&gt; &amp;mdash; 테스트를 체계적으로 실행하고 결과를 수집하기 위한 프레임워크&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Wiring Harness&lt;/b&gt; &amp;mdash; 복잡한 전선들을 체계적으로 묶고 연결하는 구조물&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공통점이 보이는가? 하네스의 본질은 &lt;b&gt;&quot;강력하지만 제멋대로인 힘을, 체계적으로 제어하고 원하는 방향으로 이끄는 구조&quot;&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code에서의 하네스도 정확히 같은 맥락이다. &lt;b&gt;AI 에이전트의 능력을 제어하고, 방향을 잡아주고, 체계적으로 작동하게 만드는 구조적 틀&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그렇다면 하네스 엔지니어링이란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스가 &quot;틀&quot;이라면, 하네스 엔지니어링은 &lt;b&gt;그 틀을 설계하고, 구축하고, 검증하고, 지속적으로 진화시키는 과정&lt;/b&gt; 전체를 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단순히 CLAUDE.md에 규칙 몇 줄 적는 것이 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다음과 같은 질문에 대한 답을 구조화하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;설계:&lt;/b&gt; 어떤 에이전트가 필요한가? 어떤 아키텍처 패턴으로 협업시킬 것인가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;구축:&lt;/b&gt; 에이전트의 역할, 원칙, 통신 프로토콜을 어떻게 정의할 것인가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;검증:&lt;/b&gt; 의도한 대로 작동하는가? 기존 자산을 보호하고 있는가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;진화:&lt;/b&gt; 실전 피드백을 어떻게 반영하고, 하네스를 어떻게 개선할 것인가?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;소프트웨어 엔지니어링이 &quot;코드를 짜는 것&quot;이 아니라 &quot;소프트웨어를 체계적으로 만드는 것&quot;인 것처럼,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링은 &lt;b&gt;&quot;AI 에이전트의 행동 체계를 엔지니어링하는 것&quot;&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스의 구성 요소&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구체적으로 하네스는 다음을 포함하는 &lt;b&gt;사전 설정(Pre-Configuration) 체계&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구성 요소&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;역할&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위치&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예시&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;CLAUDE.md&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;운영 원칙과 작업 규칙&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트 루트 또는 &lt;code&gt;~/.claude/&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;기존 코드를 함부로 재작성하지 않는다&quot;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;에이전트 정의&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;전문 역할을 가진 AI 에이전트 설계&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/agents/*.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개발 리드, 리뷰 담당, 문서 담당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;스킬&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트가 따르는 구체적 작업 절차&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/skills/*/SKILL.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅 기록 양식, 코드 리뷰 절차&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;플러그인&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;확장 기능과 워크플로우 자동화&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;settings.json&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;superpowers, code-review&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;MCP 서버&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;외부 도구와의 양방향 연동&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;settings.json&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;노션 자동 기록, Figma 디자인 연동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;한 마디로, &lt;b&gt;&quot;Claude야, 너는 이런 환경에서 이런 원칙으로 이렇게 일해&quot;&lt;/b&gt;를 코드처럼 정의해놓는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링을 위한 Claude Code 기초&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스를 설계하려면, 그 토대가 되는 Claude Code의 핵심 메커니즘을 먼저 이해해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md &amp;mdash; 프로젝트의 기억 장치&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md는 Claude Code에게 &lt;b&gt;&quot;이 프로젝트에서는 이렇게 일해&quot;&lt;/b&gt;라고 알려주는 마크다운 파일이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스의 최상위 계층이자, 모든 운영 원칙이 시작되는 곳이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;작동 방식&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;매 세션(대화) 시작 시 자동으로 로드된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재 작업 디렉토리에서 상위 디렉토리까지 순회하며 모든 CLAUDE.md를 찾아 병합한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;system prompt가 아니라 &lt;b&gt;user message 형태로&lt;/b&gt; 주입된다 (이 점이 중요한데, system prompt보다 유연하게 확장 가능하다는 뜻이다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;/compact&lt;/code&gt; 명령으로 대화를 압축해도 CLAUDE.md는 디스크에서 다시 읽어 재주입된다 &amp;mdash; 즉, 대화가 아무리 길어져도 CLAUDE.md의 규칙은 사라지지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;계층 구조 (아래로 갈수록 우선순위 높음)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;범위&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위치&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공유 범위&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;용도&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글로벌&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;본인 전체&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;모든 프로젝트 공통 원칙&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;./CLAUDE.md&lt;/code&gt; 또는 &lt;code&gt;./.claude/CLAUDE.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀 (git 추적)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트별 규칙&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;로컬&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;./CLAUDE.local.md&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;본인만&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개인 작업 환경 설정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;여러 CLAUDE.md가 발견되면 &lt;b&gt;override가 아니라 모두 병합(concatenation)&lt;/b&gt;된다. 다만 나중에 읽힌 것이 우선하므로, 프로젝트 CLAUDE.md가 글로벌보다 높은 우선순위를 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;하네스 엔지니어링 관점에서의 함의&lt;br /&gt;공식 문서에서는 CLAUDE.md를 200줄 이하로 유지할 것을 권장한다. &lt;br /&gt;내용이 길어지면 컨텍스트 윈도우 소비가 커지고, 규칙 준수율(adherence)이 떨어진다. &lt;br /&gt;이것이 하네스 엔지니어링이 단순히 &quot;규칙을 많이 적는 것&quot;이 아닌 이유다 .&lt;br /&gt;제한된 공간 안에서 최대 효과를 내는 구조를 설계해야 한다.&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트와 스킬 &amp;mdash; &quot;누가&quot;와 &quot;어떻게&quot;의 분리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code는 두 가지 핵심 확장 메커니즘을 공식적으로 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 둘의 분리가 하네스 엔지니어링의 핵심 설계 철학이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;에이전트 (Agents) &amp;mdash; &quot;누가&quot; 하는가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/agents/*.md&lt;/code&gt;에 마크다운으로 정의한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;각 에이전트는 고유한 역할, 원칙, 프로토콜을 가진다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;/agents&lt;/code&gt; 명령으로 생성/관리 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;빌트인 타입: &lt;code&gt;general-purpose&lt;/code&gt;(범용), &lt;code&gt;Explore&lt;/code&gt;(코드 탐색 전용, 읽기 전용), &lt;code&gt;Plan&lt;/code&gt;(설계 전용)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;스킬 (Skills) &amp;mdash; &quot;어떻게&quot; 하는가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/skills/*/SKILL.md&lt;/code&gt;에 YAML frontmatter + 마크다운으로 정의한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트가 작업 시 참조하는 절차적 가이드&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트리거 조건에 따라 자동 활성화되거나, 사용자가 명시적으로 호출&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 분리가 왜 중요한가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단순히 CLAUDE.md에 &quot;코드 리뷰할 때는 보안, 성능, 스타일을 체크해&quot;라고 적는 것과, 보안 전문 에이전트/성능 전문 에이전트/스타일 전문 에이전트를 각각 정의하고 코드 리뷰 스킬을 부여하는 것은 &lt;b&gt;결과물의 깊이가 다르다&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;소프트웨어 공학에서 말하는 &lt;b&gt;관심사의 분리(Separation of Concerns)&lt;/b&gt;와 같은 원리다. 하나의 거대한 모놀리스보다, 전문화된 모듈들의 조합이 더 나은 결과를 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 팀 &amp;mdash; 에이전트 간 실시간 협업&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2개 이상의 에이전트가 &lt;b&gt;실시간으로 소통하며 협업&lt;/b&gt;하는 기능이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Agent Teams는 2026년 4월 현재 여전히 Experimental 기능이다. CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 환경변수를 설정해야 활성화되며, Claude Code v2.1.32 이상이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;에이전트 팀 vs 서브 에이전트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;항목&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 팀&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서브 에이전트&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;생성 도구&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;TeamCreate&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;Agent&lt;/code&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 간 통신&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;SendMessage&lt;/code&gt;로 직접 통신 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;통신 불가, 결과만 반환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작업 조율&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공유 작업 목록으로 자체 조율&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;메인 에이전트가 모든 조율 담당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;상호 검증&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팀원 간 도전/피드백 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;불가&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;토큰 비용&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;상대적으로 높음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;효율적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;적합 상황&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2+ 에이전트 협업 필요 시&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단발성 독립 작업&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 팀의 핵심 이점은 &lt;b&gt;&quot;발견 공유, 상충 토론, 누락 보완&quot;&lt;/b&gt;이 가능하다는 점이다. 예를 들어 보안 에이전트가 발견한 취약점을 성능 에이전트가 참고해서 수정 방향을 조율할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;알려진 제한 사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;세션당 하나의 팀만 운영 가능 (단, Phase별로 팀을 해체하고 재구성할 수 있음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;중첩 팀 불가 (팀원이 자체 팀 생성 불가)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;리더 고정 (리더십 이전 불가)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;/resume&lt;/code&gt;, &lt;code&gt;/rewind&lt;/code&gt;로 세션 복원 시 teammate 복원 불가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;플러그인 시스템&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code는 공식 플러그인 마켓플레이스를 운영한다. &lt;code&gt;/plugin&lt;/code&gt; 명령으로 검색, 설치, 관리가 가능하며, 서드파티 마켓플레이스도 추가할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;플러그인은 에이전트, 스킬, 설정을 패키징한 배포 단위다. 예를 들어 &lt;code&gt;superpowers&lt;/code&gt; 플러그인은 brainstorming, TDD, debugging 등의 스킬을 한 번에 제공하고, &lt;code&gt;code-review&lt;/code&gt; 플러그인은 PR 리뷰 전용 워크플로우를 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링 관점에서 플러그인은 &lt;b&gt;&quot;이미 잘 만들어진 하네스 조각&quot;&lt;/b&gt;이다. 처음부터 모든 것을 직접 만들 필요 없이, 검증된 플러그인을 기반으로 내 프로젝트에 맞게 확장하는 접근이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;왜 하네스 엔지니어링이 필요한가&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code를 &quot;있는 그대로&quot; 쓰면 어떤 문제가 생기는지, 그리고 하네스 엔지니어링이 각 문제를 어떻게 해결하는지를 정리한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 1: 컨텍스트의 휘발성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code는 대화 세션이 끝나면 컨텍스트를 잃는다. CLAUDE.md가 이 문제를 일부 해결하지만, &quot;이 프로젝트는 Swift로 작성되었습니다&quot; 수준의 정보로는 부족하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 엔지니어링의 해법:&lt;/b&gt; 작업 방식 자체를 구조화한다. 어떤 요청이 들어오면 어떤 팀이 담당하고, 어떤 순서로 처리하고, 어떤 원칙을 지켜야 하는지가 미리 정의되어 있다. 세션이 바뀌어도 이 구조는 CLAUDE.md와 에이전트/스킬 파일에 남아있으므로, 매번 처음부터 설명할 필요가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 2: 일관성 없는 출력 품질&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같은 질문을 해도 Claude의 답변 품질이 들쭉날쭉할 때가 있다. 어떤 때는 기존 코드를 존중한 최소한의 수정안을 주고, 어떤 때는 전체 파일을 새로 작성해버린다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 엔지니어링의 해법:&lt;/b&gt; 출력의 분산을 구조적으로 줄인다. 실제로 Harness 플러그인 제작자(revfactory)가 수행한 A/B 테스트 연구 결과가 이를 뒷받침한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실험 설계: 15개 소프트웨어 엔지니어링 과제(Basic 5, Advanced 5, Expert 5)에 대해, Baseline(프롬프트만)과 Harness(.claude/ 사전 구성 포함)를 비교&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;지표&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Baseline&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 적용&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;변화&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;평균 품질 점수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;49.5&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;79.3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;+60%&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;승률&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;mdash;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;mdash;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;15전 15승 (100%)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;표준편차&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5.3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3.6&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;-32%&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;특히 과제 난이도가 높을수록 개선 효과가 증대했다 (Basic +23.8, Advanced +29.6, Expert +36.2).&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #666; font-size: 0.9em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #666; font-size: 0.9em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;출처: &lt;a href=&quot;https://github.com/revfactory/claude-code-harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/claude-code-harness&lt;/a&gt; &amp;mdash; 이 수치는 플러그인 제작자의 &lt;b&gt;자체 실험&lt;/b&gt; 결과이며 외부 독립 검증을 거친 것은 아니다. 다만 실험 설계와 원시 데이터가 GitHub에 공개되어 있어 재현 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #666; font-size: 0.9em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;수치의 신뢰도를 떠나, 시사하는 바는 명확하다. &lt;b&gt;구조화된 사전 설정이 AI 에이전트의 출력 품질과 일관성을 유의미하게 끌어올린다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 3: 기존 자산의 보호&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개인적으로 이것이 하네스 엔지니어링을 시작한 가장 큰 이유다. iOS 프로젝트에서 Claude Code를 쓰다 보면, 기존에 잘 작동하던 코드를 &quot;더 좋은&quot; 구조로 바꾸려는 시도가 빈번하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;구체적으로 겪었던 상황들&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;코드 스타일 침범:&lt;/b&gt; 프로젝트 전체가 특정 네이밍 컨벤션을 쓰고 있는데, 갑자기 다른 스타일로 코드를 작성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;아키텍처 무시:&lt;/b&gt; 기존에 MVVM으로 구성된 모듈에 MVC 패턴의 코드를 끼워넣음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;과잉 리팩토링:&lt;/b&gt; &quot;이 부분 버그 수정해줘&quot;라고 했는데 주변 코드까지 전면 재작성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;비공식 패턴 도입:&lt;/b&gt; Apple 공식 문서가 아닌 출처의 패턴을 검증 없이 적용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 엔지니어링의 해법:&lt;/b&gt; 기존 자산 보호 원칙을 구조적으로 정의한다. &quot;더 좋아 보이는 방법이 있더라도, 현재 프로젝트의 일관성과 유지보수성을 해치면 신중히 제안한다&quot; &amp;mdash; 이런 규칙이 에이전트의 행동을 제약한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 4: 지식의 소실&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code와 나눈 대화에서 유의미한 발견들이 종종 나온다. 특정 API의 숨겨진 동작, 까다로운 버그의 근본 원인, 아키텍처 결정의 근거 등. 하지만 이런 지식은 대화 세션이 끝나면 사라진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 엔지니어링의 해법:&lt;/b&gt; 기록 규칙과 외부 연동을 설계한다. 트러블슈팅 과정이나 새로운 인사이트를 정해진 양식으로 정리하고, MCP 서버를 통해 노션 같은 외부 도구에 자동 기록되는 파이프라인을 구축한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 5: 과잉 처리&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단순 구현 요청에 아키텍처 분석까지, 작은 버그 수정에 전체 모듈 리팩토링 제안까지. 작업의 크기에 맞지 않는 과도한 프로세스가 기본값이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 엔지니어링의 해법:&lt;/b&gt; 작업의 크기와 성격에 따라 호출할 팀과 프로세스 수준을 미리 분류해둔다. 간단한 구현 요청은 개발 팀만, 큰 구조 변경은 기획 + 아키텍처 + 개발 팀을 호출하는 식으로 &lt;b&gt;작업에 비례하는 프로세스&lt;/b&gt;를 설계한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스의 구성 계층&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스는 하나의 파일이 아니다. 여러 계층이 조합되어 하나의 체계를 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│               CLAUDE.md (최상위 규칙)                  │
│   운영 원칙 / 팀 구성 / 작업 흐름 / 호출 규칙 / 기록 규칙   │
├─────────────────────────────────────────────────────┤
│          에이전트 정의 (.claude/agents/*.md)            │
│      각 에이전트의 역할, 원칙, 통신 프로토콜 정의           │
│      &amp;rarr; &quot;누가&quot; 작업하는가                                │
├─────────────────────────────────────────────────────┤
│           스킬 (.claude/skills/*/SKILL.md)             │
│        에이전트가 따르는 구체적 작업 절차 정의              │
│        &amp;rarr; &quot;어떻게&quot; 작업하는가                             │
├─────────────────────────────────────────────────────┤
│          플러그인 (settings.json &amp;rarr; plugins)             │
│      사전 패키징된 에이전트/스킬 세트 (마켓플레이스)         │
├─────────────────────────────────────────────────────┤
│         MCP 서버 (settings.json &amp;rarr; mcpServers)          │
│        외부 도구 양방향 연동 (노션, Figma 등)              │
├─────────────────────────────────────────────────────┤
│                  settings.json                        │
│          모델, 플러그인 활성화, LSP, 언어 설정             │
└─────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;각 계층은 독립적으로도 의미가 있지만, 조합했을 때 비로소 &lt;b&gt;&quot;체계&quot;&lt;/b&gt;가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md에 &quot;트러블슈팅은 이 양식으로 정리해&quot;라고 규칙을 적는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅 전문 에이전트를 &lt;code&gt;.claude/agents/troubleshooter.md&lt;/code&gt;에 정의한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트러블슈팅 스킬을 &lt;code&gt;.claude/skills/troubleshoot/SKILL.md&lt;/code&gt;에 작성한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;노션 MCP 서버를 연결한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이렇게 하면 버그를 해결할 때 &amp;rarr; 트러블슈팅 에이전트가 활성화되고 &amp;rarr; 정해진 스킬에 따라 원인을 분석하고 &amp;rarr; 결과를 노션 DB에 자동 기록하는 파이프라인이 완성된다. 이것이 하네스 엔지니어링이 추구하는 &lt;b&gt;end-to-end 자동화&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 플러그인 &amp;mdash; 하네스 엔지니어링 도구&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위에서 설명한 하네스 체계를 직접 처음부터 설계할 수도 있지만, &lt;b&gt;Harness 플러그인&lt;/b&gt;을 활용하면 이 과정을 체계적으로 가이드받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 플러그인이란&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;a href=&quot;https://github.com/revfactory/harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/harness&lt;/a&gt;는 Claude Code 플러그인으로 설치할 수 있는 &lt;b&gt;메타 스킬(Meta-Skill)&lt;/b&gt;이다. &quot;메타&quot;라고 부르는 이유는, 이 스킬 자체가 다른 에이전트와 스킬을 &lt;b&gt;생성&lt;/b&gt;하는 스킬이기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;하네스 구성해줘&quot;라고 말하면, 사용자의 도메인에 맞는 에이전트 팀과 스킬을 자동으로 설계하고, &lt;code&gt;.claude/agents/&lt;/code&gt;와 &lt;code&gt;.claude/skills/&lt;/code&gt; 디렉토리에 파일을 생성하고, CLAUDE.md에 하네스 컨텍스트를 등록하는 것까지 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; background-color: #f5f5f5; width: 120px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;현재 버전&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1.1.0 (2026-04-05 릴리스)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; background-color: #f5f5f5;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;라이선스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Apache 2.0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; background-color: #f5f5f5;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;제작자&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;robin (revfactory)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; background-color: #f5f5f5;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;초기 릴리스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1.0.0 (2026-03-27)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6가지 아키텍처 패턴&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링에서 가장 중요한 설계 결정 중 하나가 &lt;b&gt;&quot;에이전트들을 어떤 구조로 협업시킬 것인가&quot;&lt;/b&gt;다. Harness 플러그인은 6가지 아키텍처 패턴을 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 파이프라인 (Pipeline)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;[분석] &amp;rarr; [설계] &amp;rarr; [구현] &amp;rarr; [검증]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;각 단계가 이전 단계의 산출물에 강하게 의존하는 &lt;b&gt;순차 작업&lt;/b&gt;에 적합하다. 기획 &amp;rarr; 개발 &amp;rarr; 리뷰처럼 단계적 의존이 있을 때 사용한다. 에이전트 팀의 이점이 제한적이지만, 단계 내에 병렬 구간이 있으면 유용하다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 팬아웃/팬인 (Fan-out/Fan-in)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;         ┌&amp;rarr; [전문가 A] ─┐
[입력] ──┼&amp;rarr; [전문가 B] ──┼&amp;rarr; [통합]
         └&amp;rarr; [전문가 C] ─┘&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하나의 입력을 여러 전문가에게 분배하고, 병렬 처리 후 결과를 통합한다. &lt;b&gt;에이전트 팀의 가장 자연스러운 패턴&lt;/b&gt;이다. 코드 리뷰에서 보안/성능/스타일을 동시에 분석하거나, 리서치에서 공식 문서/커뮤니티/학술 자료를 동시에 조사할 때 적합하다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3. 전문가 풀 (Expert Pool)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;[라우터] ──&amp;rarr; 상황에 따라 ──&amp;rarr; [전문가 A] 또는 [전문가 B] 또는 [전문가 C]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;모든 전문가가 항상 활성화되는 것이 아니라, 상황에 따라 필요한 전문가만 선택 호출한다. &lt;b&gt;서브 에이전트 모드가 더 적합&lt;/b&gt;한 패턴이다 (불필요한 에이전트가 상시 대기할 필요 없으므로).&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4. 생성-검증 (Producer-Reviewer)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[생성] &amp;rarr; [검증] &amp;rarr; 문제 시 &amp;rarr; [생성] 재실행 (최대 2~3회)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;산출물의 품질 보장이 중요하고 객관적 검증 기준이 존재할 때 사용한다. 에이전트 팀 모드에서 &lt;code&gt;SendMessage&lt;/code&gt;로 실시간 피드백을 주고받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5. 감독자 (Supervisor)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;[감독자] ──&amp;rarr; 상태 확인 후 동적 분배 ──&amp;rarr; [작업자 A] / [작업자 B] / [작업자 C]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팬아웃과 비슷하지만, 사전 고정 분배가 아니라 &lt;b&gt;진행 상황에 따라 동적으로 작업을 조정&lt;/b&gt;한다. 에이전트 팀의 공유 작업 목록(&lt;code&gt;TaskCreate&lt;/code&gt;/&lt;code&gt;TaskUpdate&lt;/code&gt;)과 자연스럽게 맞는다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6. 계층적 위임 (Hierarchical Delegation)&lt;/span&gt;&lt;/h4&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;[총괄] &amp;rarr; [팀장 A] &amp;rarr; [실무자 1, 2]
       &amp;rarr; [팀장 B] &amp;rarr; [실무자 3, 4]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;큰 작업을 재귀적으로 나눠서 위임한다. 다만 에이전트 팀은 중첩이 불가하므로, 1단계는 에이전트 팀으로 구성하고 2단계 이하는 서브 에이전트로 구현해야 한다. 깊이 3단계 이상은 지연과 컨텍스트 손실이 커지므로 &lt;b&gt;2단계 이내가 권장&lt;/b&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;복합 패턴&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실전에서는 단일 패턴보다 복합 패턴이 더 흔하다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;조합&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예시&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;팬아웃 + 생성-검증&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4개 언어 병렬 번역 &amp;rarr; 각각 네이티브 리뷰어 검수&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;파이프라인 + 팬아웃&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;분석(순차) &amp;rarr; 구현(병렬) &amp;rarr; 통합 테스트(순차)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;감독자 + 전문가 풀&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;고객 문의 분류 후 적합한 전문가 할당&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;워크플로우 (Phase 0~7)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 1.1.0 기준, 하네스 엔지니어링은 다음 단계로 진행된다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center; width: 80px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Phase&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left; width: 140px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이름&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설명&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;현황 감사&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 &lt;code&gt;.claude/agents/&lt;/code&gt;, &lt;code&gt;.claude/skills/&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;를 확인하고, 신규 구축 / 기존 확장 / 운영 유지보수 중 하나로 분기&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;도메인 분석&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트의 기술 스택, 데이터 모델, 주요 모듈 파악. 사용자 숙련도를 감지해 이후 커뮤니케이션 톤을 조절&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;팀 아키텍처 설계&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트 팀 vs 서브 에이전트 결정, 6가지 아키텍처 패턴 중 선택, 에이전트 분리 기준(전문성/병렬성/컨텍스트/재사용성) 적용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;에이전트 정의 생성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/agents/*.md&lt;/code&gt; 파일 생성 (핵심 역할, 작업 원칙, 입출력 프로토콜, 에러 핸들링). 세션 중단 대비 CLAUDE.md 임시 동기화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;스킬 생성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;code&gt;.claude/skills/*/SKILL.md&lt;/code&gt; 파일 생성. CLAUDE.md 임시 동기화&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;통합 및 오케스트레이션&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;CLAUDE.md에 하네스 컨텍스트 최종 등록 (에이전트 팀 구조, 스킬 목록, 실행 규칙, 디렉토리 구조)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;검증 및 테스트&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;트리거 검증, 드라이런 테스트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;7&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;하네스 진화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실행 후 피드백 수집 &amp;rarr; 피드백 유형별 수정 대상 매핑 &amp;rarr; 변경 이력 기록 &amp;rarr; 자동 진화 트리거&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Phase 0과 Phase 7은 1.1.0에서 추가된 기능이다. 하네스를 &quot;한 번 만들면 끝&quot;이 아니라, &lt;b&gt;지속적으로 감사하고 진화시키는 시스템&lt;/b&gt;으로 설계한 것이 이 플러그인의 차별점이다. 이것이 바로 하네스 &quot;엔지니어링&quot;이라고 부르는 이유 &amp;mdash; &lt;b&gt;설계 &amp;rarr; 구축 &amp;rarr; 검증 &amp;rarr; 진화&lt;/b&gt;의 전체 라이프사이클을 다루기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설치 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;방법 1: 마켓플레이스 (권장)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude Code 터미널에서 실행:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;# 1. 서드파티 마켓플레이스 등록
/plugin marketplace add revfactory/harness

# 2. 플러그인 설치
/plugin install harness@harness&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;방법 2: 글로벌 스킬 직접 설치&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;GitHub에서 클론한 뒤 skills 디렉토리를 복사:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cp -r skills/harness ~/.claude/skills/harness&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;필수 환경 변수 (에이전트 팀 기능 사용 시):&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설치 후 &quot;하네스 구성해줘&quot; 또는 &quot;하네스 설계해줘&quot;라고 말하면 Phase 0부터 자동으로 시작된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제 활용 사례 &amp;mdash; Harness 100&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Harness 플러그인의 범용성을 보여주는 프로젝트로 &lt;a href=&quot;https://github.com/revfactory/harness-100&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/harness-100&lt;/a&gt;이 있다. 10개 도메인에 걸쳐 &lt;b&gt;100개의 프로덕션 레디 하네스&lt;/b&gt;를 이 플러그인으로 생성한 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;도메인&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예시&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;콘텐츠 제작&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;웹툰 제작, 유튜브 기획, 기술 문서 작성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;소프트웨어 개발&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코드 리뷰, 마이그레이션, 풀스택 웹 개발&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;데이터/AI&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;데이터 파이프라인, ML 모델 검증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비즈니스 전략&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;마케팅 캠페인, 시장 분석&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그 외&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;교육, 법률, 헬스케어, 커뮤니케이션, 운영 등&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;한국어/영어 200개 패키지, 에이전트 정의 978개, 스킬 630개, 총 1,808개 마크다운 파일로 구성되어 있다. 하네스 엔지니어링이 소프트웨어 개발에만 국한되지 않고 다양한 도메인에 적용 가능하다는 것을 보여주는 사례다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링 vs 단순 CLAUDE.md 작성&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;그냥 CLAUDE.md에 규칙 몇 줄 적으면 되는 거 아니야?&quot;라고 생각할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;맞다, CLAUDE.md만으로도 기본적인 규칙 설정은 가능하다. 하지만 하네스 엔지니어링과는 차원이 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5;&quot;&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;관점&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단순 CLAUDE.md&lt;/span&gt;&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 10px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;역할 분리&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Claude 하나가 모든 걸 처리&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;전문 에이전트가 역할별로 분담&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;품질 검증&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;자기가 만들고 자기가 판단&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;생성자와 검증자가 구조적으로 분리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;일관성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;규칙은 있지만 준수 강제력 약함&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트별 원칙과 프로토콜로 구조적 보장&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;규칙이 늘면 파일이 비대해짐&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이전트/스킬 파일로 분산 관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;재사용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로젝트마다 다시 작성&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;패턴화된 구조를 재활용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;외부 연동&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;수동 복사/붙여넣기&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;MCP로 노션, Figma 등 자동 연동&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;진화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;수동으로 규칙 추가/수정&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;피드백 기반 자동 진화 메커니즘&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비유하자면, 단순 CLAUDE.md는 &lt;b&gt;&quot;팀원 한 명에게 긴 메모를 건네는 것&quot;&lt;/b&gt;이고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링은 &lt;b&gt;&quot;조직을 설계하고, 역할을 나누고, 업무 매뉴얼을 만들고, 성과 피드백 시스템까지 구축하는 것&quot;&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;내가 하네스 엔지니어링을 시작한 이유&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;iOS 개발자로서 Claude Code를 쓰면서 반복적으로 겪은 문제들이 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;1. 기존 코드 파괴&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;잘 작동하는 코드를 &quot;모던한&quot; 방식으로 전면 재작성하려는 경향. 단순히 버그 하나 수정해달라고 했는데 주변 코드까지 리팩토링해버리는 경우가 빈번했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;2. 컨텍스트 망각&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;매 세션마다 프로젝트 구조, 아키텍처, 코드 스타일을 다시 설명해야 했다. CLAUDE.md에 기본 정보를 적어둬도, &quot;어떻게 일해야 하는지&quot;까지는 담기 어려웠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;3. 일관성 부재&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같은 유형의 작업인데 매번 다른 방식으로 처리했다. 트러블슈팅을 할 때 어떤 세션에서는 체계적으로 원인을 분석하고, 어떤 세션에서는 대충 &quot;이거 바꿔보세요&quot; 수준의 답을 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;4. 기록 누락&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;중요한 트러블슈팅이나 인사이트가 대화 속에 묻혀 사라졌다. 나중에 비슷한 문제를 만났을 때 &quot;전에 이거 해결했었는데...&quot; 하며 기억을 더듬어야 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;5. 과잉 처리&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;단순 구현 요청에 아키텍처 분석까지, 작은 버그 수정에 전체 모듈 리팩토링 제안까지. 작업의 크기에 맞지 않는 과도한 프로세스가 기본값이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하네스 엔지니어링은 이 모든 문제에 대한 &lt;b&gt;구조적 해답&lt;/b&gt;을 줄 수 있을거라 생각했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;규칙을 한 번 설계해두면, 매 세션마다 Claude가 그 규칙 안에서 작동한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기존 자산을 보호하고, 작업을 분류하고, 필요한 수준의 팀만 호출하고, 기록할 것은 기록한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다음 편에서는 내가 실제로 CLAUDE.md에 어떤 오케스트레이터 시스템을 설계했는지 &amp;mdash; 6개 팀의 구성, 4인 역할 구조, 운영 원칙, 팀 호출 규칙, 비효율 경고 시스템까지 상세히 다뤄보려 한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #888; font-size: 0.85em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;이 글에서 언급된 도구와 리소스&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://code.claude.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Claude Code&lt;/a&gt; &amp;mdash; Anthropic의 공식 AI 코딩 에이전트&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://github.com/revfactory/harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/harness&lt;/a&gt; &amp;mdash; Claude Code 하네스 구성 플러그인 (Apache 2.0)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://github.com/revfactory/claude-code-harness&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/claude-code-harness&lt;/a&gt; &amp;mdash; Harness A/B 테스트 연구 데이터&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://github.com/revfactory/harness-100&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;revfactory/harness-100&lt;/a&gt; &amp;mdash; 10개 도메인 100개 하네스 컬렉션&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://code.claude.com/docs/en/memory&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Claude Code 공식 문서 - Memory&lt;/a&gt; &amp;mdash; CLAUDE.md 작동 방식&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;bull; &lt;a href=&quot;https://code.claude.com/docs/en/agent-teams&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Claude Code 공식 문서 - Agent Teams&lt;/a&gt; &amp;mdash; 에이전트 팀 기능&lt;/span&gt;&lt;/p&gt;</description>
      <category>Claude</category>
      <category>Agent</category>
      <category>ai</category>
      <category>Claude</category>
      <category>claude code</category>
      <category>Harness</category>
      <category>IOS</category>
      <category>revfactory/harness</category>
      <category>공공돌</category>
      <category>클로드</category>
      <category>클로드 코드</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/189</guid>
      <comments>https://sheep1sik.tistory.com/189#entry189comment</comments>
      <pubDate>Wed, 8 Apr 2026 18:56:36 +0900</pubDate>
    </item>
    <item>
      <title>[ Algorithm ] Baekjoon_1002 : C++</title>
      <link>https://sheep1sik.tistory.com/188</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;C++로 백준 1002번 터렛 문제를 풀면서 기하학 개념 없이도 접근할 수 있는 방법을 정리해봤다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제 이해&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 문제를 처음 봤을 때 지문이 어려워서 이해가 잘 안 됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;핵심만 정리하면 이렇다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 사람(조규현, 백승환)이 각각 자기 위치에서 적까지의 거리를 알고 있다. 조규현은 좌표 (x1, y1)에 있고 적까지 거리가 r1, 백승환은 좌표 (x2, y2)에 있고 적까지 거리가 r2이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이걸 기하학적으로 생각하면 각 사람을 중심으로 반지름만큼의 &lt;b&gt;원&lt;/b&gt;을 그릴 수 있다. 적은 그 원 둘레 어딘가에 있는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;결국 이 문제의 본질은 &lt;b&gt;두 원의 교점이 몇 개인지&lt;/b&gt; 구하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;쉬운 비유&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기하학을 모르더라도 이렇게 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;운동장에 두 사람이 서 있다. 각자 줄을 하나씩 들고 있는데, 줄 끝에 적이 있다. 첫 번째 사람 줄 길이가 r1이고, 두 번째 사람 줄 길이가 r2이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;핵심은 &lt;b&gt;두 사람이 얼마나 떨어져 있느냐&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 사람이 &lt;b&gt;너무 멀리&lt;/b&gt; 서 있으면 &amp;rarr; 줄을 아무리 뻗어도 안 닿는다 &amp;rarr; 적이 있을 수 있는 곳이 없다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;적당한 거리&lt;/b&gt;로 서 있으면 &amp;rarr; 줄이 겹치는 지점이 두 군데 생긴다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;딱 맞는 거리&lt;/b&gt;면 &amp;rarr; 겹치는 지점이 한 군데&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;같은 자리&lt;/b&gt;에 서 있고 줄 길이도 같으면 &amp;rarr; 어디든 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;경우의 수 정리&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 원이 만나는 경우는 총 5가지로 나뉜다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;아래 그림을 보면 한눈에 이해할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;summary_all_cases.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nS0wB/dJMcagSBfMk/5lCWiElfabIImqeKWTYCT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nS0wB/dJMcagSBfMk/5lCWiElfabIImqeKWTYCT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nS0wB/dJMcagSBfMk/5lCWiElfabIImqeKWTYCT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnS0wB%2FdJMcagSBfMk%2F5lCWiElfabIImqeKWTYCT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;301&quot; data-filename=&quot;summary_all_cases.png&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하나씩 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;case1_too_far.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lAfO6/dJMcabDKP2E/eVAYQuw0QrFXhd5OSki4k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lAfO6/dJMcabDKP2E/eVAYQuw0QrFXhd5OSki4k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lAfO6/dJMcabDKP2E/eVAYQuw0QrFXhd5OSki4k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlAfO6%2FdJMcabDKP2E%2FeVAYQuw0QrFXhd5OSki4k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;346&quot; data-filename=&quot;case1_too_far.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 원이 너무 멀리 떨어져 있어서 아예 만나지 않는다. 두 사람 사이 거리(d)가 두 줄 길이의 합(r1 + r2)보다 클 때 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;case2_touch_outside.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOWht8/dJMcadhfTGI/IvK1V7fk4uElLKKrCoxU3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOWht8/dJMcadhfTGI/IvK1V7fk4uElLKKrCoxU3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOWht8/dJMcadhfTGI/IvK1V7fk4uElLKKrCoxU3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOWht8%2FdJMcadhfTGI%2FIvK1V7fk4uElLKKrCoxU3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;628&quot; height=&quot;359&quot; data-filename=&quot;case2_touch_outside.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 원이 바깥쪽에서 딱 한 점에서만 닿는다. d = r1 + r2일 때 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;case3_two_points.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bja493/dJMcabqeGs5/szKdQGTn67vxrfdytkPu7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bja493/dJMcabqeGs5/szKdQGTn67vxrfdytkPu7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bja493/dJMcabqeGs5/szKdQGTn67vxrfdytkPu7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbja493%2FdJMcabqeGs5%2FszKdQGTn67vxrfdytkPu7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;579&quot; height=&quot;331&quot; data-filename=&quot;case3_two_points.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 원이 겹치면서 두 군데에서 만난다. |r1 - r2| &amp;lt; d &amp;lt; r1 + r2일 때 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;case4_inside.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzE2IY/dJMcaakxkBo/KBn7k0KUvo7UZ3lKXE1pE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzE2IY/dJMcaakxkBo/KBn7k0KUvo7UZ3lKXE1pE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzE2IY/dJMcaakxkBo/KBn7k0KUvo7UZ3lKXE1pE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzE2IY%2FdJMcaakxkBo%2FKBn7k0KUvo7UZ3lKXE1pE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;586&quot; height=&quot;335&quot; data-filename=&quot;case4_inside.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작은 원이 큰 원 안에 완전히 들어가서 만나지 않는다. d &amp;lt; |r1 - r2|일 때 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;case5_same.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JFwkP/dJMcaco7NDj/RirqjazfCHdTBNoVdzu9FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JFwkP/dJMcaco7NDj/RirqjazfCHdTBNoVdzu9FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JFwkP/dJMcaco7NDj/RirqjazfCHdTBNoVdzu9FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJFwkP%2FdJMcaco7NDj%2FRirqjazfCHdTBNoVdzu9FK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;346&quot; data-filename=&quot;case5_same.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 사람이 같은 위치에 있고 줄 길이도 같으면 원이 완전히 겹친다. 만나는 점이 무한대이므로 -1을 출력한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;d는 어떻게 구할까?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;d는 두 사람 사이의 거리다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;두 사람의 좌표가 주어지니까 거리를 구할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예를 들어 (1, 1)과 (4, 5)라면&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;가로 차이 = 4 - 1 = 3
세로 차이 = 5 - 1 = 4

거리의 제곱 = 3 * 3 + 4 * 4 = 9 + 16 = 25
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;여기서 루트를 씌우면 거리가 5가 되는데, 코드에서는 &lt;b&gt;루트를 씌우지 않고 제곱 상태로 비교&lt;/b&gt;한다. 왜냐하면 루트를 씌우면 소수점 오차가 생길 수 있기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;참고로 순서를 바꿔서 (x1 - x2) 대신 (x2 - x1)로 해도 결과는 같다. 어차피 제곱하면 마이너스가 사라지기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비교 기준 준비&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;d를 구했으면 비교할 값 두 개를 미리 만들어둔다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;sum = (r1 + r2) * (r1 + r2)    &amp;rarr; 두 줄 길이 합의 제곱
diff = (r1 - r2) * (r1 - r2)   &amp;rarr; 두 줄 길이 차의 제곱
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;sum&lt;/b&gt;은 두 사람이 줄을 최대한 뻗었을 때 닿을 수 있는 가장 먼 거리다. 두 사람 사이 거리가 이것보다 크면 아무리 해도 안 만난다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;diff&lt;/b&gt;는 두 줄 길이의 차이다. 두 사람 사이 거리가 이것보다 작으면 작은 원이 큰 원 안에 쏙 들어가서 안 만난다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;우선순위&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;조건을 확인하는 순서가 중요하다. 위에서부터 하나씩 걸러내면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;완전히 같은 원인지 확인&lt;/b&gt; &amp;rarr; d = 0이고 r1 = r2면 &amp;rarr; -1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;같은 위치인데 줄 길이가 다른지 확인&lt;/b&gt; &amp;rarr; d = 0이고 r1 &amp;ne; r2면 &amp;rarr; 0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;너무 멀거나 안에 쏙 들어가는지 확인&lt;/b&gt; &amp;rarr; d &amp;gt; sum 또는 d &amp;lt; diff면 &amp;rarr; 0&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;딱 닿는지 확인&lt;/b&gt; &amp;rarr; d = sum 또는 d = diff면 &amp;rarr; 1&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;나머지&lt;/b&gt; &amp;rarr; 2&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코드&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int t;
    cin &amp;gt;&amp;gt; t;

    for (int i = 0; i &amp;lt; t; i++) {
        double x1, y1, r1, x2, y2, r2;
        cin &amp;gt;&amp;gt; x1 &amp;gt;&amp;gt; y1 &amp;gt;&amp;gt; r1 &amp;gt;&amp;gt; x2 &amp;gt;&amp;gt; y2 &amp;gt;&amp;gt; r2;

        // 두 사람 사이 거리의 제곱
        double d = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);

        // 비교할 값들도 제곱 상태로 준비
        double sum = (r1 + r2) * (r1 + r2);
        double diff = (r1 - r2) * (r1 - r2);

        // 우선순위대로 조건 확인
        if (d == 0 &amp;amp;&amp;amp; r1 == r2) {
            cout &amp;lt;&amp;lt; -1 &amp;lt;&amp;lt; &quot;\n&quot;;
        }
        else if (d == 0 &amp;amp;&amp;amp; r1 != r2) {
            cout &amp;lt;&amp;lt; 0 &amp;lt;&amp;lt; &quot;\n&quot;;
        }
        else if (d &amp;gt; sum || d &amp;lt; diff) {
            cout &amp;lt;&amp;lt; 0 &amp;lt;&amp;lt; &quot;\n&quot;;
        }
        else if (d == sum || d == diff) {
            cout &amp;lt;&amp;lt; 1 &amp;lt;&amp;lt; &quot;\n&quot;;
        }
        else {
            cout &amp;lt;&amp;lt; 2 &amp;lt;&amp;lt; &quot;\n&quot;;
        }
    }

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;정리&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;백준 1002번 터렛은 기하학 문제처럼 보이지만, 결국 &lt;b&gt;두 원의 위치 관계&lt;/b&gt;를 판별하는 문제다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;핵심은 세 가지 값을 비교하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;d&lt;/b&gt;: 두 사람 사이 거리의 제곱&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;sum&lt;/b&gt;: 두 반지름 합의 제곱&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;diff&lt;/b&gt;: 두 반지름 차의 제곱&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 세 값만 비교하면 어떤 경우인지 알 수 있다. 작은 조건 분기를 정확히 나누는 것이 이 문제의 핵심이라고 생각한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Algorithm/Baekjoon</category>
      <category>algorithm</category>
      <category>BOJ</category>
      <category>BOJ_1002</category>
      <category>C++</category>
      <category>공공돌</category>
      <category>기하학</category>
      <category>백준</category>
      <category>백준 터렛</category>
      <category>알고리즘</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/188</guid>
      <comments>https://sheep1sik.tistory.com/188#entry188comment</comments>
      <pubDate>Mon, 6 Apr 2026 17:57:46 +0900</pubDate>
    </item>
    <item>
      <title>[C++] 코딩테스트에서 endl 대신 &amp;quot;\n&amp;quot;을 써야 하는 이유</title>
      <link>https://sheep1sik.tistory.com/187</link>
      <description>&lt;p data-end=&quot;226&quot; data-start=&quot;185&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;C++로 알고리즘 문제를 풀다 보면 자연스럽게 이런 코드를 작성하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; endl;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;338&quot; data-start=&quot;259&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;줄바꿈을 할 때 endl을 사용하는 것은 매우 흔한 습관이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그런데 코딩테스트 관련 글을 보다 보면 이런 이야기를 자주 접하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-end=&quot;367&quot; data-start=&quot;340&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;367&quot; data-start=&quot;342&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&quot;endl 대신 \n을 사용하라.&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;369&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;369&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;둘 다 줄바꿈을 하는데 왜 굳이 \n을 써야 할까?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;정말 성능 차이가 있는 걸까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;441&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;궁금해서 직접 실험을 통해 확인해봤다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;464&quot; data-start=&quot;448&quot; data-section-id=&quot;7m40un&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;endl과 &quot;\n&quot;의 차이&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;491&quot; data-start=&quot;466&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;표면적으로 보면 두 방식은 같은 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048348996&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cout &amp;lt;&amp;lt; &quot;Hello&quot; &amp;lt;&amp;lt; endl;
cout &amp;lt;&amp;lt; &quot;Hello\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;566&quot; data-start=&quot;549&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;둘 다 출력 후 줄바꿈을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;591&quot; data-start=&quot;568&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하지만 내부 동작에는 중요한 차이가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;동작 방식&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;666&quot; data-start=&quot;593&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;666&quot; data-start=&quot;615&quot;&gt;
&lt;tr data-end=&quot;645&quot; data-start=&quot;615&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;624&quot; data-start=&quot;615&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;endl&lt;/span&gt;&lt;/td&gt;
&lt;td data-end=&quot;645&quot; data-start=&quot;624&quot; data-col-size=&quot;sm&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;줄바꿈 + 출력 버퍼 flush&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;666&quot; data-start=&quot;646&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;655&quot; data-start=&quot;646&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;/td&gt;
&lt;td data-end=&quot;666&quot; data-start=&quot;655&quot; data-col-size=&quot;sm&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;줄바꿈만 수행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;688&quot; data-start=&quot;668&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;여기서 핵심은 &lt;b&gt;flush&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;709&quot; data-start=&quot;695&quot; data-section-id=&quot;1tlgazn&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;출력 버퍼와 flush&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;753&quot; data-start=&quot;711&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;cout으로 출력한다고 해서 데이터가 바로 화면에 나타나는 것은 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;796&quot; data-start=&quot;755&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;C++의 출력은 **버퍼(buffer)**라는 임시 저장 공간을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;815&quot; data-start=&quot;798&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;동작 흐름은 대략 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048300163&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cout &amp;rarr; 버퍼에 저장 &amp;rarr; 버퍼가 차면 한 번에 출력&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;889&quot; data-start=&quot;857&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이렇게 하는 이유는 &lt;b&gt;입출력 성능을 높이기 위해서&lt;/b&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;934&quot; data-start=&quot;891&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하지만 &lt;b&gt;flush&lt;/b&gt;는 이 버퍼를 &lt;b&gt;즉시 비우고 출력하도록 강제&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048306748&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cout &amp;rarr; 버퍼 &amp;rarr; flush &amp;rarr; 즉시 출력&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1015&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제는 endl이 &lt;b&gt;줄바꿈을 할 때마다 flush를 실행한다는 점&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1060&quot; data-start=&quot;1017&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;즉 출력이 많을수록 flush가 계속 발생하면서 성능이 크게 떨어질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;1079&quot; data-start=&quot;1067&quot; data-section-id=&quot;qutzci&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이해하기 쉬운 비유&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;1108&quot; data-start=&quot;1081&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 상황을 택배 배송으로 비유하면 이해하기 쉽다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-end=&quot;1121&quot; data-start=&quot;1110&quot; data-section-id=&quot;zblyep&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;endl 방식&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1773048276130&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;물건 1개 넣음 &amp;rarr; 바로 배송
물건 1개 넣음 &amp;rarr; 바로 배송
물건 1개 넣음 &amp;rarr; 바로 배송&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1194&quot; data-start=&quot;1183&quot; data-section-id=&quot;zq17b4&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;\n&quot; 방식&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048286806&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;물건을 모음 &amp;rarr; 박스가 가득 참 &amp;rarr; 한 번에 배송&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1255&quot; data-start=&quot;1233&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;당연히 두 번째 방식이 훨씬 효율적이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;1279&quot; data-start=&quot;1262&quot; data-section-id=&quot;1n5gw8x&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제로 얼마나 차이가 날까?&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;1320&quot; data-start=&quot;1281&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이론적으로는 느리다고 하지만 &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제로 얼마나 차이가 나는지 궁금했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1359&quot; data-start=&quot;1322&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그래서 &lt;b&gt;100만 번 출력하는 간단한 테스트 코드&lt;/b&gt;를 작성했다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773047905674&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);

int N = 1000000;

// endl 테스트
auto start1 = chrono::high_resolution_clock::now();
for (int i = 0; i &amp;lt; N; i++) {
cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl;
}
auto end1 = chrono::high_resolution_clock::now();
double time1 = chrono::duration&amp;lt;double&amp;gt;(end1 - start1).count();

// &quot;\n&quot; 테스트
auto start2 = chrono::high_resolution_clock::now();
for (int i = 0; i &amp;lt; N; i++) {
cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; &quot;\n&quot;;
}
auto end2 = chrono::high_resolution_clock::now();
double time2 = chrono::duration&amp;lt;double&amp;gt;(end2 - start2).count();

cerr &amp;lt;&amp;lt; &quot;endl: &quot; &amp;lt;&amp;lt; time1 &amp;lt;&amp;lt; &quot;초\n&quot;;
cerr &amp;lt;&amp;lt; &quot;\\n: &quot; &amp;lt;&amp;lt; time2 &amp;lt;&amp;lt; &quot;초\n&quot;;
cerr &amp;lt;&amp;lt; &quot;차이: &quot; &amp;lt;&amp;lt; time1 / time2 &amp;lt;&amp;lt; &quot;배\n&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;2171&quot; data-start=&quot;2164&quot; data-section-id=&quot;74zg0u&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;측정 결과&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;2178&quot; data-start=&quot;2173&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실행 환경&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2211&quot; data-start=&quot;2180&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2187&quot; data-start=&quot;2180&quot; data-section-id=&quot;1658dej&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;macOS&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2196&quot; data-start=&quot;2188&quot; data-section-id=&quot;1cpimbq&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;g++-15&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2211&quot; data-start=&quot;2197&quot; data-section-id=&quot;18q6fvg&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;-O2 최적화 옵션&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2228&quot; data-start=&quot;2213&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;측정 결과는 다음과 같았다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;endl: 약 1.037초&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;\n&quot;: 약 0.066초&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2271&quot; data-start=&quot;2269&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;즉, &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;endl이 약 15배 이상 느렸다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2331&quot; data-start=&quot;2298&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같은 100만 번 출력인데도 성능 차이가 꽤 크게 나타났다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;2354&quot; data-start=&quot;2338&quot; data-section-id=&quot;1n37ap6&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코딩테스트에서 중요한 이유&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;2388&quot; data-start=&quot;2356&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;코딩테스트에서는 출력이 매우 많은 문제들이 종종 등장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2395&quot; data-start=&quot;2390&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예를 들어&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2432&quot; data-start=&quot;2397&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2413&quot; data-start=&quot;2397&quot; data-section-id=&quot;1lnicbj&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;N이 &lt;b&gt;100,000&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2432&quot; data-start=&quot;2414&quot; data-section-id=&quot;ntrbz4&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;혹은 &lt;b&gt;1,000,000&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2499&quot; data-start=&quot;2434&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같이 출력이 반복되는 경우, endl을 사용하면 &lt;b&gt;flush가 반복 실행되면서 시간 초과가 발생할 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2534&quot; data-start=&quot;2501&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그래서 나는 알고리즘 풀이에서 아래와 같이 설정을 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048191239&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  ios::sync_with_stdio(false);  // C/C++ 입출력 동기화 해제 &amp;rarr; 속도 &amp;uarr;
  cin.tie(NULL);                 // cin-cout 연결 해제 &amp;rarr; 불필요한 flush 방지&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2602&quot; data-start=&quot;2592&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그리고 출력할 때는 아래와 같이&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&quot;\n&quot;을 사용하는 것이 일반적이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773048158605&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; &quot;\n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h1 data-end=&quot;2671&quot; data-start=&quot;2667&quot; data-section-id=&quot;yim43j&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;정리&lt;/span&gt;&lt;/h1&gt;
&lt;p data-end=&quot;2706&quot; data-start=&quot;2673&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;C++에서 endl과 &quot;\n&quot;의 차이는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;방식 특징&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;2786&quot; data-start=&quot;2708&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2786&quot; data-start=&quot;2730&quot;&gt;
&lt;tr data-end=&quot;2765&quot; data-start=&quot;2730&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2739&quot; data-start=&quot;2730&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;endl&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2765&quot; data-start=&quot;2739&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;줄바꿈 + flush (버퍼 즉시 비움)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2786&quot; data-start=&quot;2766&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2775&quot; data-start=&quot;2766&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2786&quot; data-start=&quot;2775&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;줄바꿈만 수행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2839&quot; data-start=&quot;2788&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;출력이 적다면 큰 차이는 없지만 &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;대량 출력에서는 성능 차이가 매우 커질 수 있다고 생각한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2839&quot; data-start=&quot;2788&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2939&quot; data-start=&quot;2897&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작은 습관 하나지만 &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;시간 초과를 막는 중요한 차이&lt;/b&gt;가 될 수 있다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>C++</category>
      <category>endl</category>
      <category>공공돌</category>
      <category>백준</category>
      <category>입출력 최적화</category>
      <category>코딩 테스트</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/187</guid>
      <comments>https://sheep1sik.tistory.com/187#entry187comment</comments>
      <pubDate>Mon, 9 Mar 2026 18:28:04 +0900</pubDate>
    </item>
    <item>
      <title>자식 컨트롤러 누락으로 인한 이벤트 미작동</title>
      <link>https://sheep1sik.tistory.com/186</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rx 바인딩도 정상적으로 되어 있고, 버튼 액션도 설정했지만, &lt;b&gt;버튼을 눌러도 로그가 찍히지 않고 이미지도 변경되지 않음&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 setChecked(_: Bool)이나 @objc 메서드들이 호출되지 않는 상태.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 체크박스가 포함된 InfoRowView는 WorkingConditionsContainerViewController의 view에 존재함.&lt;/li&gt;
&lt;li&gt;하지만 &lt;b&gt;최종 부모 컨트롤러에서 해당 VC를 자식 뷰컨트롤러로 등록하지 않고 view만 addSubview()&lt;/b&gt; 하여 붙였음.&lt;/li&gt;
&lt;li&gt;이로 인해 viewDidLoad()가 호출되지 않았고, 내부에서 설정된 &lt;b&gt;Rx 바인딩 및 addTarget 등의 액션 로직이 실행되지 않음&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WorkingConditionsContainerViewController를&amp;nbsp;자식&amp;nbsp;컨트롤러로&amp;nbsp;명시적으로&amp;nbsp;등록하고,&amp;nbsp;그&amp;nbsp;뷰를&amp;nbsp;container에&amp;nbsp;붙이도록&amp;nbsp;수정&lt;/p&gt;
&lt;pre id=&quot;code_1753257525085&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;extension UIViewController {
    func add(_ child: UIViewController, to container: UIView) {
        addChild(child)
        container.addSubview(child.view)
        child.view.snp.makeConstraints { $0.edges.equalToSuperview() }
        child.didMove(toParent: self)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 부모 컨트롤러에서 다음과 같이 호출&lt;/p&gt;
&lt;pre id=&quot;code_1753257554285&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;add(workingConditionsContainerViewController, to: workingConditionsContainer)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>트러블 슈팅</category>
      <category>IOS</category>
      <category>SWIFT</category>
      <category>UIKit</category>
      <category>공공돌</category>
      <category>트러블 슈팅</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/186</guid>
      <comments>https://sheep1sik.tistory.com/186#entry186comment</comments>
      <pubDate>Wed, 23 Jul 2025 17:00:30 +0900</pubDate>
    </item>
    <item>
      <title>체크박스를 클릭해도 이미지가 바뀌지 않음</title>
      <link>https://sheep1sik.tistory.com/185</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;checkBox.isSelected = isChecked 호출이 동작하지 않음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그도 찍히지 않음.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setChecked(_:)는 호출되었지만, 해당 메서드가 뷰 계층이 제대로 올라가지 않은 상태에서 동작하고 있었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 버튼에 target-action이 제대로 설정되지 않았음.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;checkBox.addTarget(_:action:for:)는 뷰 외부(컨트롤러 또는 초기화 시점)에서 설정&lt;/li&gt;
&lt;li&gt;InfoRowView 내에서 .checkBox 타입일 경우에만 touchUpInside 설정&lt;/li&gt;
&lt;li&gt;타겟 등록 이후 setChecked(_:) 호출로 UI 갱신&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1753257323109&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// MARK: - setStyles
    func setStyles(type: InfoRowType) {
        switch type {
        case .checkBox(let isChecked):
            checkBox.isSelected = isChecked
            checkBox.addTarget(self, action: #selector(didTapCheckBox), for: .touchUpInside)
        case .labelWithChevron(let value):
            valueLabel.text = value
        case .labelWithButton(let title):
            actionButton.setTitle(title, for: .normal)
        case .colorWithChevron(let color, let title):
            colorDotView.backgroundColor = color
            titleLabel.text = title
            
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1753257356840&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// MARK: - Public Methods
    func setChecked(_ isChecked: Bool) {
        checkBox.isSelected = isChecked
    }
    
    func isChecked() -&amp;gt; Bool {
        return checkBox.isSelected
    }
    
    @objc private func didTapCheckBox() {
        checkTappedRelay.accept(())
    }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>트러블 슈팅</category>
      <category>IOS</category>
      <category>SWIFT</category>
      <category>UIKit</category>
      <category>공공돌</category>
      <category>트러블 슈팅</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/185</guid>
      <comments>https://sheep1sik.tistory.com/185#entry185comment</comments>
      <pubDate>Wed, 23 Jul 2025 16:56:24 +0900</pubDate>
    </item>
    <item>
      <title>[ iOS ] Apple 로그인 클라이언트 구현 (UIKit + Rx + Clean Architecture)</title>
      <link>https://sheep1sik.tistory.com/184</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이 글은 UIKit 기반 앱에서 Apple 로그인을 구현하는 전 과정을 다룹니다.&lt;br /&gt;RxSwift, MVVM, 클린 아키텍처, 서버 연동을 기준으로 작성되었습니다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;307&quot; data-start=&quot;276&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Apple Developer 계정 로그인&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;409&quot; data-start=&quot;309&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;387&quot; data-start=&quot;309&quot;&gt;&lt;a href=&quot;https://developer.apple.com/account&quot;&gt;https://developer.apple.com/account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1753171449151&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;로그인 - Apple&quot; data-og-description=&quot;&quot; data-og-host=&quot;idmsa.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/account&quot; data-og-url=&quot;https://idmsa.apple.com/IDMSWebAuth/signin?appIdKey=891bd3417a7776362562d2197f89480a8547b108fd934911bcbea0110d07f757&amp;amp;path=%2Faccount%2F&amp;amp;rv=1&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.apple.com/account&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/account&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;로그인 - Apple&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;idmsa.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;440&quot; data-start=&quot;416&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. App ID 생성 (식별자)&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;718&quot; data-start=&quot;442&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;503&quot; data-start=&quot;442&quot;&gt;좌측 메뉴 &amp;rarr; &lt;b&gt;Certificates, IDs &amp;amp; Profiles&lt;/b&gt; &amp;rarr; &lt;b&gt;Identifiers&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;541&quot; data-start=&quot;504&quot;&gt;&lt;b&gt;+&lt;/b&gt; 버튼 클릭 &amp;rarr; App IDs &amp;rarr; &lt;b&gt;App&lt;/b&gt; 선택&lt;/li&gt;
&lt;li data-end=&quot;569&quot; data-start=&quot;542&quot;&gt;&lt;b&gt;Description&lt;/b&gt;: 앱 이름 입력&lt;/li&gt;
&lt;li data-end=&quot;643&quot; data-start=&quot;570&quot;&gt;&lt;b&gt;Bundle ID&lt;/b&gt;: Xcode에서 사용하는 것과 &lt;b&gt;정확히 일치&lt;/b&gt;하도록 입력 (예: com.example.app)&lt;/li&gt;
&lt;li data-end=&quot;691&quot; data-start=&quot;644&quot;&gt;&lt;b&gt;Capabilities&lt;/b&gt;에서 &lt;b&gt;Sign In with Apple&lt;/b&gt; 체크&lt;/li&gt;
&lt;li data-end=&quot;718&quot; data-start=&quot;692&quot;&gt;&lt;b&gt;Continue &amp;rarr; Register&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o&quot; data-message-id=&quot;a367c7de-b137-441e-a6a9-21326bdb0d97&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-end=&quot;825&quot; data-start=&quot;795&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Service ID 생성 (웹 인증용)&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1274&quot; data-start=&quot;827&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;872&quot; data-start=&quot;827&quot;&gt;&lt;b&gt;Identifiers&lt;/b&gt; &amp;rarr; &lt;b&gt;+&lt;/b&gt; &amp;rarr; &lt;b&gt;Services IDs&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;918&quot; data-start=&quot;873&quot;&gt;&lt;b&gt;Identifier&lt;/b&gt;: 예: com.example.app.login&lt;/li&gt;
&lt;li data-end=&quot;965&quot; data-start=&quot;919&quot;&gt;&lt;b&gt;Description&lt;/b&gt;: 예: Apple Login for MyApp&lt;/li&gt;
&lt;li data-end=&quot;995&quot; data-start=&quot;966&quot;&gt;생성 후 목록에서 해당 Service ID 선택&lt;/li&gt;
&lt;li data-end=&quot;1018&quot; data-start=&quot;996&quot;&gt;&lt;b&gt;Configure&lt;/b&gt; 버튼 클릭&lt;/li&gt;
&lt;li data-end=&quot;1047&quot; data-start=&quot;1019&quot;&gt;&lt;b&gt;Sign in with Apple&lt;/b&gt; 체크&lt;/li&gt;
&lt;li data-end=&quot;1087&quot; data-start=&quot;1048&quot;&gt;&lt;b&gt;Primary App ID&lt;/b&gt;: 방금 생성한 App ID 선택&lt;/li&gt;
&lt;li data-end=&quot;1155&quot; data-start=&quot;1088&quot;&gt;&lt;b&gt;Web domain&lt;/b&gt;: 앱에서 사용할 서버 도메인 입력 (예: &lt;a href=&quot;https://your-domain.com&quot;&gt;https://your-domain.com&lt;/a&gt;)&lt;/li&gt;
&lt;li data-end=&quot;1260&quot; data-start=&quot;1156&quot;&gt;&lt;b&gt;Return URL&lt;/b&gt;: 서버에서 Apple 인증 처리를 받을 콜백 URL 입력 (예: &lt;a href=&quot;https://your-domain.com/api/auth/apple/callback&quot;&gt;https://your-domain.com/api/auth/apple/callback&lt;/a&gt;)&lt;/li&gt;
&lt;li data-end=&quot;1274&quot; data-start=&quot;1261&quot;&gt;저장 후 Done&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;1301&quot; data-start=&quot;1281&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. Auth Key 생성&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1467&quot; data-start=&quot;1303&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1322&quot; data-start=&quot;1303&quot;&gt;좌측 메뉴 &amp;rarr; &lt;b&gt;Keys&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1337&quot; data-start=&quot;1323&quot;&gt;&lt;b&gt;+&lt;/b&gt; 버튼 클릭&lt;/li&gt;
&lt;li data-end=&quot;1375&quot; data-start=&quot;1338&quot;&gt;&lt;b&gt;Key Name&lt;/b&gt;: 예: Apple Login Key&lt;/li&gt;
&lt;li data-end=&quot;1404&quot; data-start=&quot;1376&quot;&gt;&lt;b&gt;Sign In with Apple&lt;/b&gt; 체크&lt;/li&gt;
&lt;li data-end=&quot;1441&quot; data-start=&quot;1405&quot;&gt;&lt;b&gt;Configure&lt;/b&gt; &amp;rarr; Primary App ID 선택&lt;/li&gt;
&lt;li data-end=&quot;1467&quot; data-start=&quot;1442&quot;&gt;완료 후 Key 다운로드 (.p8 파일)&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-end=&quot;1521&quot; data-start=&quot;1469&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1521&quot; data-start=&quot;1471&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Auth Key는 단 한 번만 다운로드 가능하므로 안전한 곳에 보관하세요.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-end=&quot;1553&quot; data-start=&quot;1528&quot; data-ke-size=&quot;size23&quot;&gt;5. 클라이언트에서 필요한 값 정리 및 백엔드 공유&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;저의 경우 Slack을 통해서 백엔드분에게 아래와 같이 공유 드렸습니다 !&amp;nbsp;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-07-22 오후 5.16.17.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;1196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF9LyC/btsPtzTfaKy/iHTZzZ9bm553tIMauNsyQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF9LyC/btsPtzTfaKy/iHTZzZ9bm553tIMauNsyQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF9LyC/btsPtzTfaKy/iHTZzZ9bm553tIMauNsyQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF9LyC%2FbtsPtzTfaKy%2FiHTZzZ9bm553tIMauNsyQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;603&quot; height=&quot;1073&quot; data-filename=&quot;스크린샷 2025-07-22 오후 5.16.17.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;1196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;373&quot; data-start=&quot;358&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 프로젝트 설정&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;420&quot; data-start=&quot;375&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1-1. Sign in with Apple Capabilities 추가&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;463&quot; data-start=&quot;422&quot; data-ke-size=&quot;size16&quot;&gt;Xcode에서 Apple 로그인 기능을 사용하려면 해당 권한이 필요합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;613&quot; data-start=&quot;465&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;511&quot; data-start=&quot;465&quot;&gt;Xcode &amp;gt; Target &amp;gt; &lt;b&gt;Signing &amp;amp; Capabilities&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;535&quot; data-start=&quot;512&quot;&gt;+ Capability 버튼 클릭&lt;/li&gt;
&lt;li data-end=&quot;564&quot; data-start=&quot;536&quot;&gt;&lt;b&gt;Sign In with Apple&lt;/b&gt; 선택&lt;/li&gt;
&lt;li data-end=&quot;564&quot; data-start=&quot;536&quot;&gt;자동으로 .entitlements 파일이 생성되며 아래 내용이 포함되어야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1753170810059&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;key&amp;gt;com.apple.developer.applesignin&amp;lt;/key&amp;gt;
&amp;lt;array&amp;gt;
    &amp;lt;string&amp;gt;Default&amp;lt;/string&amp;gt;
&amp;lt;/array&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLtyet/btsPuKsESrY/0lzcTwLbitdkrHAg580ftk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLtyet/btsPuKsESrY/0lzcTwLbitdkrHAg580ftk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLtyet/btsPuKsESrY/0lzcTwLbitdkrHAg580ftk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLtyet%2FbtsPuKsESrY%2F0lzcTwLbitdkrHAg580ftk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;736&quot; height=&quot;551&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;747&quot; data-start=&quot;721&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Apple 로그인 버튼 UI 추가&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;773&quot; data-start=&quot;749&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2-1. Apple 로그인 버튼 생성&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;LoginView&lt;/h4&gt;
&lt;pre id=&quot;code_1753170878492&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import UIKit
import SnapKit
import Then
import AuthenticationServices

final class LoginView: UIView {
    // MARK: - Properties
    
    // MARK: - UI Components
    
    var appleLoginButton = ASAuthorizationAppleIDButton().then {
        $0.cornerRadius = 8
        $0.translatesAutoresizingMaskIntoConstraints = false
    }

    // MARK: - Initializer
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        configure()
    }
    
    @available(*, unavailable, message: &quot;storyboard is not supported.&quot;)
    required init?(coder: NSCoder) {
        fatalError(&quot;init(coder:) has not been implemented.&quot;)
    }
    
    // MARK: - Public Methods
}

private extension LoginView {
    // MARK: - configure
    func configure() {
        setHierarchy()
        setStyles()
        setConstraints()
    }
    
    // MARK: - setHierarchy
    func setHierarchy() {
        addSubview(appleLoginButton)
    }
    
    // MARK: - setStyles
    func setStyles() {
        backgroundColor = .white
    }
    
    // MARK: - setConstraints
    func setConstraints() {
        appleLoginButton.snp.makeConstraints {
            $0.centerX.equalToSuperview()
            $0.bottom.equalToSuperview().inset(40)
            $0.height.equalTo(50)
            $0.width.equalTo(280)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Apple 로그인 로직 구현 (AuthRepository)&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1753171067959&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;final class AuthRepositoryImpl: AuthRepository {

    private var appleAuthDelegate: AppleAuthDelegate?

    func loginWithApple() -&amp;gt; Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt; {
        return Observable.create { observer in
            let provider = ASAuthorizationAppleIDProvider()
            let request = provider.createRequest()
            request.requestedScopes = [.fullName, .email]

            let controller = ASAuthorizationController(authorizationRequests: [request])

            let delegate = AppleAuthDelegate { result in
                observer.onNext(result)
                observer.onCompleted()
            }

            self.appleAuthDelegate = delegate
            controller.delegate = delegate
            controller.presentationContextProvider = delegate
            controller.performRequests()

            print(&quot;Apple 로그인 요청 시작됨&quot;)
            return Disposables.create()
        }
    }

    func sendCodeToServer(code: String) -&amp;gt; Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt; {
        let url = URL(string: &quot;https://your-server.com/api/auth/apple/callback&quot;)!
        var request = URLRequest(url: url)
        request.httpMethod = &quot;POST&quot;
        request.setValue(&quot;application/json&quot;, forHTTPHeaderField: &quot;Content-Type&quot;)

        let body = [&quot;code&quot;: code]
        request.httpBody = try? JSONSerialization.data(withJSONObject: body)

        return URLSession.shared.rx.response(request: request)
            .map { response, data in
                let resultBody = String(data: data, encoding: .utf8) ?? &quot;&quot;
                print(&quot;응답: \(response.statusCode), body: \(resultBody)&quot;)

                if 200..&amp;lt;300 ~= response.statusCode {
                    return .success(&quot;로그인 성공&quot;)
                } else {
                    return .failure(NSError(domain: &quot;auth&quot;, code: response.statusCode, userInfo: [NSLocalizedDescriptionKey: resultBody]))
                }
            }
            .catch { .just(.failure($0)) }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;AppleAuthDelegate 구현&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1753171138484&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;final class AppleAuthDelegate: NSObject, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {

    private let completion: (Result&amp;lt;String, Error&amp;gt;) -&amp;gt; Void

    init(completion: @escaping (Result&amp;lt;String, Error&amp;gt;) -&amp;gt; Void) {
        self.completion = completion
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
           let codeData = credential.authorizationCode,
           let code = String(data: codeData, encoding: .utf8) {
            print(&quot;인증 성공, code: \(code)&quot;)
            completion(.success(code))
        } else {
            completion(.failure(NSError(domain: &quot;apple&quot;, code: -1, userInfo: [NSLocalizedDescriptionKey: &quot;Code decode error&quot;])))
        }
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        completion(.failure(error))
    }

    func presentationAnchor(for controller: ASAuthorizationController) -&amp;gt; ASPresentationAnchor {
        return UIApplication.shared.windows.first ?? UIWindow()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. UseCase 구현&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1753171170310&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;final class LoginWithAppleUseCaseImpl: LoginWithAppleUseCase {
    private let repository: AuthRepository

    init(repository: AuthRepository) {
        self.repository = repository
    }

    func execute() -&amp;gt; Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt; {
        return repository.loginWithApple()
            .flatMap { result in
                switch result {
                case .success(let code):
                    return self.repository.sendCodeToServer(code: code)
                case .failure(let error):
                    return .just(.failure(error))
                }
            }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. ViewModel &amp;amp; ViewController&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1753171294493&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Foundation
import RxSwift
import RxCocoa

protocol LoginViewModelInput {
    var appleLoginTapped: PublishRelay&amp;lt;Void&amp;gt; { get }
}

protocol LoginViewModelOutput {
    var loginResult: Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt; { get }
}

final class LoginViewModel: LoginViewModelInput, LoginViewModelOutput {

    // Input
    let appleLoginTapped = PublishRelay&amp;lt;Void&amp;gt;()

    // Output
    let loginResult: Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt;

    // Private
    private let loginUseCase: LoginWithAppleUseCase
    private let disposeBag = DisposeBag()
    private let loginResultRelay = PublishRelay&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt;()

    init(loginUseCase: LoginWithAppleUseCase) {
        self.loginUseCase = loginUseCase
        self.loginResult = loginResultRelay.asObservable()
        bind()
    }

    private func bind() {
        appleLoginTapped
            .do(onNext: { print(&quot;Apple 로그인 버튼 탭&quot;) })
            .flatMapLatest { [weak self] _ -&amp;gt; Observable&amp;lt;Result&amp;lt;String, Error&amp;gt;&amp;gt; in
                guard let self = self else { return .empty() }
                return self.loginUseCase.execute()
            }
            .bind(to: loginResultRelay)
            .disposed(by: disposeBag)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1753171364839&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import UIKit
import AuthenticationServices
import RxSwift
import RxCocoa

final class LoginViewController: UIViewController {
    
    // MARK: - Properties
    private let loginView = LoginView()
    private let viewModel: LoginViewModel
    private let disposeBag = DisposeBag()
    
    // MARK: - Initializer
    
    init(viewModel: LoginViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    @available(*, unavailable, message: &quot;Storyboard is not supported&quot;)
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    // MARK: - Lifecycle
    
    override func loadView() {
        self.view = loginView
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configure()
    }
    
    @objc func didTapAppleLogin() {
        viewModel.appleLoginTapped.accept(())
    }
}

// MARK: - UI Methods

private extension LoginViewController {
    
    func configure() {
        setHierarchy()
        setStyles()
        setConstraints()
        setActions()
        setBinding()
    }
    
    func setHierarchy() {

    }
    
    func setStyles() {

    }
    
    func setConstraints() {

    }
    
    func setActions() {
        loginView.appleLoginButton.addTarget(self, action: #selector(didTapAppleLogin), for: .touchUpInside)
    }
    
    func setBinding() {
        viewModel.loginResult
            .observe(on: MainScheduler.instance)
            .subscribe(onNext: { [weak self] result in
                switch result {
                case .success(let code):
                    print(&quot;로그인 성공, 인증 코드: \(code)&quot;)
                    // TODO: &amp;rarr; 다음 화면으로 전환
                case .failure(let error):
                    print(&quot;로그인 실패: \(error.localizedDescription)&quot;)
                    // TODO: &amp;rarr; 사용자에게 Alert 등 UI 처리
                }
            })
            .disposed(by: disposeBag)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1753174365139&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;애플 로그인 설정하기&quot; data-og-description=&quot;참고: 같은 이름(닉네임)으로 중복 가입 방지 옵션을 해제해 주세요. 소셜 로그인 가입자는 대부분 가입된 플랫폼의 이름(닉네임)을 그대로 사용하는 경향이 있으며, 소셜 로그인 플랫&quot; data-og-host=&quot;imweb.me&quot; data-og-source-url=&quot;https://imweb.me/faq?mode=view&amp;amp;category=29&amp;amp;category2=47&amp;amp;idx=71719&quot; data-og-url=&quot;https://imweb.me/faq?category=29&amp;amp;category2=47&amp;amp;idx=71719&amp;amp;mode=view&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ceMhyV/hyZniAkr3G/NKdm5tCvHYxwaiQTL6RxZK/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/VkXsN/hyZnbA9rAP/fm3au4B38Kr4phtw2aFJR1/img.png?width=960&amp;amp;height=640&amp;amp;face=0_0_960_640,https://scrap.kakaocdn.net/dn/48xeT/hyZnDc69Rd/yZEkrHsLqbK7iWcTxvJsik/img.png?width=1045&amp;amp;height=480&amp;amp;face=0_0_1045_480&quot;&gt;&lt;a href=&quot;https://imweb.me/faq?mode=view&amp;amp;category=29&amp;amp;category2=47&amp;amp;idx=71719&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://imweb.me/faq?mode=view&amp;amp;category=29&amp;amp;category2=47&amp;amp;idx=71719&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ceMhyV/hyZniAkr3G/NKdm5tCvHYxwaiQTL6RxZK/img.png?width=2400&amp;amp;height=1260&amp;amp;face=0_0_2400_1260,https://scrap.kakaocdn.net/dn/VkXsN/hyZnbA9rAP/fm3au4B38Kr4phtw2aFJR1/img.png?width=960&amp;amp;height=640&amp;amp;face=0_0_960_640,https://scrap.kakaocdn.net/dn/48xeT/hyZnDc69Rd/yZEkrHsLqbK7iWcTxvJsik/img.png?width=1045&amp;amp;height=480&amp;amp;face=0_0_1045_480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;애플 로그인 설정하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;참고: 같은 이름(닉네임)으로 중복 가입 방지 옵션을 해제해 주세요. 소셜 로그인 가입자는 대부분 가입된 플랫폼의 이름(닉네임)을 그대로 사용하는 경향이 있으며, 소셜 로그인 플랫&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;imweb.me&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1753174387715&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Sign in with Apple | Apple Developer Documentation&quot; data-og-description=&quot;Provide users the ability to sign in to your apps and websites using their Apple ID.&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/documentation/signinwithapple&quot; data-og-url=&quot;https://docs.developer.apple.com/documentation/signinwithapple&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/hyscQ/hyZncmxNyS/cpJ5Zkds19KyOSf4Xd5My0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bIFqjb/hyZnjTuEB7/e98qrm7bwscYAFw5YVuhaK/img.jpg?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://developer.apple.com/documentation/signinwithapple&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/documentation/signinwithapple&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/hyscQ/hyZncmxNyS/cpJ5Zkds19KyOSf4Xd5My0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bIFqjb/hyZnjTuEB7/e98qrm7bwscYAFw5YVuhaK/img.jpg?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Sign in with Apple | Apple Developer Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Provide users the ability to sign in to your apps and websites using their Apple ID.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1753174400033&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Sign in with Apple REST API | Apple Developer Documentation&quot; data-og-description=&quot;Communicate between your app servers and Apple&amp;rsquo;s authentication servers.&quot; data-og-host=&quot;developer.apple.com&quot; data-og-source-url=&quot;https://developer.apple.com/documentation/signinwithapplerestapi&quot; data-og-url=&quot;https://docs.developer.apple.com/documentation/signinwithapplerestapi&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/WLCoX/hyZnAm9UIi/ishbFeRvjxhKkk8d2Bvk2k/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ixjeB/hyZntauM1I/WjC9m320KYfVFFYJlJ1gM1/img.jpg?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://developer.apple.com/documentation/signinwithapplerestapi&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.apple.com/documentation/signinwithapplerestapi&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/WLCoX/hyZnAm9UIi/ishbFeRvjxhKkk8d2Bvk2k/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ixjeB/hyZntauM1I/WjC9m320KYfVFFYJlJ1gM1/img.jpg?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Sign in with Apple REST API | Apple Developer Documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Communicate between your app servers and Apple&amp;rsquo;s authentication servers.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>IOS</category>
      <category>SWIFT</category>
      <category>UIKit</category>
      <category>공공돌</category>
      <category>애플 로그인</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/184</guid>
      <comments>https://sheep1sik.tistory.com/184#entry184comment</comments>
      <pubDate>Tue, 22 Jul 2025 17:51:15 +0900</pubDate>
    </item>
    <item>
      <title>AutoLayout - 화면 겹침 현상 (StackView 내 CustomView 겹침)</title>
      <link>https://sheep1sik.tistory.com/183</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div data-message-id=&quot;9901dbf0-a833-4155-a19a-1f7077c08ea0&quot; data-message-author-role=&quot;user&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZE93q/btsPotddnXy/DFt2Qp3CEIHezkFAytWVC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZE93q/btsPotddnXy/DFt2Qp3CEIHezkFAytWVC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZE93q/btsPotddnXy/DFt2Qp3CEIHezkFAytWVC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZE93q%2FbtsPotddnXy%2FDFt2Qp3CEIHezkFAytWVC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;340&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UIStackView 내부에 WorkplaceContainerView, PayContainerView를 배치했음에도 불구하고, 두 뷰가 겹쳐서 출력되는 현상이 발생&lt;/li&gt;
&lt;li&gt;내부 요소들이 정상적으로 구성되었음에도 StackView가 자식 뷰의 높이를 인식하지 못해 UI가 깨짐&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UIStackView는 자식 뷰의 &lt;b&gt;명시적인 높이 제약 또는 intrinsic content size&lt;/b&gt;가 없는 경우, 뷰의 높이를 0으로 인식함&lt;/li&gt;
&lt;li&gt;WorkplaceContainerView와 PayContainerView 모두 내부에 UI를 배치한 container 뷰만 있고, 해당 뷰의 하단 요소를 기준으로 전체 높이를 계산하는 제약이 빠져있었음&lt;/li&gt;
&lt;li&gt;distribution을 .equalSpacing으로 설정한 것도 자식 뷰 간의 간격 계산을 비정상적으로 만들 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결 방안&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 컨테이너 뷰(WorkplaceContainerView, PayContainerView)의 하단에 다음 제약을 추가하여, &lt;b&gt;자신의 높이를 내부 container 기준으로 결정&lt;/b&gt;하도록 유도&lt;/li&gt;
&lt;li&gt;StackView의&amp;nbsp;&lt;b&gt;distribution&lt;/b&gt;을&amp;nbsp;&lt;b&gt;.fill&lt;/b&gt;로&amp;nbsp;변경하여&amp;nbsp;높이&amp;nbsp;계산을&amp;nbsp;자동으로&amp;nbsp;처리하도록&amp;nbsp;수정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1752747779693&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;self.snp.makeConstraints {
    $0.bottom.equalTo(container.snp.bottom)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1752747862045&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;stackView.distribution = .fill&lt;/code&gt;&lt;/pre&gt;</description>
      <category>트러블 슈팅</category>
      <category>AutoLayout</category>
      <category>IOS</category>
      <category>SWIFT</category>
      <category>공공돌</category>
      <category>트러블 슈팅</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/183</guid>
      <comments>https://sheep1sik.tistory.com/183#entry183comment</comments>
      <pubDate>Thu, 17 Jul 2025 19:24:45 +0900</pubDate>
    </item>
    <item>
      <title>NSAttributedString - 적용 순서로 인해 강조 색상이 반영되지 않음</title>
      <link>https://sheep1sik.tistory.com/182</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UILabel에서 &quot;근무지 *&quot;와 같이 특정 문자를 강조하려 했으나 에 적용한 색상이 반영되지 않음&lt;/li&gt;
&lt;li&gt;NSMutableAttributedString을 사용했음에도 불구하고 문자가 회색(gray900)으로 표시되어 의도한 빨간색(accent)이 보이지 않는 문제 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NSMutableAttributedString은 &lt;b&gt;속성을 덮어쓰기 방식으로 적용&lt;/b&gt;됨&lt;/li&gt;
&lt;li&gt;전체 문자열에 .foregroundColor = gray900를 &lt;b&gt;마지막에&lt;/b&gt; 적용하면서,&lt;/li&gt;
&lt;li&gt;앞서 설정한 *에 대한 빨간색 설정이 &lt;b&gt;덮어써져 무효화&lt;/b&gt;됨&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결방안&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 스타일(전체 폰트 및 색상)은 먼저 설정하고&lt;/li&gt;
&lt;li&gt;특정 부분 강조()는 &lt;b&gt;가장 마지막에 스타일을 적용&lt;/b&gt;하도록 순서 조정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1752747689730&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private let workplaceTitle = UILabel().then {
    let fullText = &quot;근무지 *&quot;
    let attributed = NSMutableAttributedString(string: fullText)

    // 전체 스타일 먼저
    attributed.addAttribute(.font, value: UIFont.headBold(18), range: NSRange(location: 0, length: fullText.count))
    attributed.addAttribute(.foregroundColor, value: UIColor.gray900, range: NSRange(location: 0, length: fullText.count))

    // '*'만 마지막에 다시 색상 덮어쓰기
    if let starRange = fullText.range(of: &quot;*&quot;) {
        let nsRange = NSRange(starRange, in: fullText)
        attributed.addAttribute(.foregroundColor, value: UIColor.accent, range: nsRange)
    }

    $0.attributedText = attributed
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>트러블 슈팅</category>
      <category>IOS</category>
      <category>NSAttributedString</category>
      <category>SWIFT</category>
      <category>공공돌</category>
      <category>트러블 슈팅</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/182</guid>
      <comments>https://sheep1sik.tistory.com/182#entry182comment</comments>
      <pubDate>Thu, 17 Jul 2025 19:22:02 +0900</pubDate>
    </item>
    <item>
      <title>[ Coordinator ] Coordinator 패턴이란?</title>
      <link>https://sheep1sik.tistory.com/181</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Coordinator&amp;nbsp;패턴이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코디네이터(Coordinator) 패턴은&amp;nbsp;&lt;b&gt;iOS 앱에서 ViewController의 &quot;화면 전환&quot; 책임을 분리&lt;/b&gt;하여, 별도의 객체인 코디네이터가 화면 흐름과 네비게이션을 관리하도록 하는 디자인 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 패턴의 핵심 목적은&amp;nbsp;&lt;b&gt;ViewController의 역할을 단순화&lt;/b&gt;하고,&amp;nbsp;&lt;b&gt;화면 간 전환에 따른 결합도를 낮추는 것&lt;/b&gt;이 목적이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;왜 코디네이터 패턴이 필요할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Coordinator 객체는 화면 전환(네비게이션)과 관련된 모든 로직을 담당하게 되는데 ViewController는 더 이상 다른 ViewController를 직접 생성하거나, 네비게이션을 직접 수행하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ViewController는 단지 자신의 코디네이터에게 &quot;다음 화면으로 이동해달라&quot;고 요청만 할 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Coordinator 프로토콜 예시&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;swiftprotocol Coordinator: AnyObject {
    var childCoordinators: [Coordinator] { get set }
    var navigationController: UINavigationController { get set }
    func start()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;childCoordinators&lt;/b&gt;: 하위 플로우(예: 회원가입, 상세화면 등)를 관리하는 코디네이터 배열&lt;/li&gt;
&lt;li&gt;&lt;b&gt;navigationController&lt;/b&gt;: 화면 전환에 사용할 네비게이션 컨트롤러&lt;/li&gt;
&lt;li&gt;&lt;b&gt;start()&lt;/b&gt;: 해당 플로우의 시작점(초기 화면을 띄우는 역할)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;동작 방식&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;앱의 시작점(AppDelegate/SceneDelegate)에서 루트 코디네이터(AppCoordinator 등)를 생성&lt;/b&gt;하고, start()를 호출하여 화면 흐름을 시작합니다.&lt;/li&gt;
&lt;li&gt;루트 코디네이터는 필요에 따라 하위 코디네이터(TabBarCoordinator, HomeCoordinator 등)를 생성하고, 각 코디네이터의 start()를 호출합니다.&lt;/li&gt;
&lt;li&gt;각 코디네이터는 자신이 담당하는 ViewController를 생성하고, 필요 시 ViewController에 자신(coordinator)을 주입합니다.&lt;/li&gt;
&lt;li&gt;ViewController에서 화면 전환이 필요할 때, 직접 push/present하지 않고 자신의 코디네이터에게 요청합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;단일 책임 원칙(SRP)&lt;/b&gt;&amp;nbsp;준수: ViewController는 UI와 이벤트만, Coordinator는 네비게이션만 담당.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유지보수성&lt;/b&gt;: 화면 전환 로직이 한 곳에 모여 있어 수정이 쉽고, ViewController 간의 결합도가 낮아집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;재사용성&lt;/b&gt;: ViewController를 다른 플로우에서도 쉽게 재사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 용이성&lt;/b&gt;: 네비게이션 로직을 별도로 테스트할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코디네이터 패턴&lt;/b&gt;은 ViewController의 네비게이션 책임을 분리해 코드의 결합도를 낮추고, 유지보수성과 확장성을 높이는 iOS 아키텍처 패턴이다. 실제 구현은 프로젝트와 팀의 스타일에 따라 조금씩 다를 수 있지만, 핵심은 &quot;화면 전환 책임을 ViewController가 아닌 Coordinator가 진다&quot;는 점이다.&lt;/p&gt;</description>
      <category>Design Pattern</category>
      <category>Coordinator</category>
      <category>IOS</category>
      <category>SWIFT</category>
      <category>공공돌</category>
      <category>디자인 패턴</category>
      <author>Sheep1sik</author>
      <guid isPermaLink="true">https://sheep1sik.tistory.com/181</guid>
      <comments>https://sheep1sik.tistory.com/181#entry181comment</comments>
      <pubDate>Mon, 14 Jul 2025 17:07:06 +0900</pubDate>
    </item>
  </channel>
</rss>