<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>김종권의 iOS 앱 개발 알아가기</title>
    <link>https://ios-development.tistory.com/</link>
    <description>iOS개발을 위해서 필요한 지식을 공유 하는 블로그</description>
    <language>ko</language>
    <pubDate>Tue, 7 Jul 2026 04:27:01 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jake-kim</managingEditor>
    <image>
      <title>김종권의 iOS 앱 개발 알아가기</title>
      <url>https://tistory1.daumcdn.net/tistory/3812930/attach/1dd1ccd271264acdb363bd5a484b4b12</url>
      <link>https://ios-development.tistory.com</link>
    </image>
    <item>
      <title>[AI] 1. Claude Code 병렬 처리로 효율 극대화하기 - git worktree 기본 개념</title>
      <link>https://ios-development.tistory.com/1857</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;[AI] Claude Code 병렬 처리로 효율 극대화하기 - git worktree 기본 개념&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1858&quot;&gt;[AI] Claude Code 병렬 처리로 효율 극대화하기 (claude --worktree)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;background-color: #ffffff; color: #6bacce; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1859&quot;&gt;[AI] Claude Code 병렬 처리로 효율 극대화하기 - tmux 활용하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1860&quot;&gt;[AI] Claude Code 병렬 처리로 효율 극대화하기 - git worktree 기본 개념&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1861&quot;&gt;Claude Code 병렬 처리로 효율 극대화하기 - cmux, worktree, omc 병렬 처리하기 (.omc/handoffs, .omc/shared_memory.json)&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;worktree가 왜 중요한가&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;Claude Code나 GitHub Copilot CLI 같은 터미널 기반 AI 도구를 쓸 때 아쉬운 점이 있음.&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;AI에게 무거운 리팩토링이나 테스트 코드 작성을 시켜두면, 작업이 끝날 때까지 해당 브랜치에서 키보드를 놓고 대기해야 함. 중간에 브랜치를 바꾸면 코드가 뒤엉키기 때문&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;이러한 컨텍스트 스위칭 비용과 병목 현상을 해결해 주는 Git 기능이 바로 git worktree&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;Claude Code를 병렬로 띄워두고 멀티태스킹을 하기 위한 핵심 전제 조건인 Git Worktree의 개념과 기본 사용법을 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size20&quot;&gt;1. Git Worktree란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;9&quot;&gt;일반적인 git clone 환경에서는 단 하나의 작업 디렉토리(Working Directory)만 존재&lt;/li&gt;
&lt;li data-path-to-node=&quot;9&quot;&gt;git checkout으로 브랜치를 바꾸면 하나의 폴더 안에서 파일이 순간적으로 바뀌므로, &lt;b data-index-in-node=&quot;51&quot; data-path-to-node=&quot;10&quot;&gt;동시에 펼쳐놓고 작업할 수 있는 브랜치는 늘 단 1개&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;뿐&lt;/span&gt;&lt;/li&gt;
&lt;li data-path-to-node=&quot;9&quot;&gt;반면, &lt;b data-index-in-node=&quot;4&quot; data-path-to-node=&quot;11&quot;&gt;Git Worktree는 하나의 Git 저장소(.git)를 공유하면서, 서로 다른 브랜치를 바라보는 '물리적인 폴더'를 여러 개 생성하는 기능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size20&quot;&gt;  개념 구분하기: worktree와 branch 차이?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;기존 브랜치 방식:&lt;/b&gt; main에서 파일 코드를 10줄쯤 고치던 중, 급하게 bugfix 브랜치로 넘어가야 하면 그냥 바꿀 수 없음. Git이 &quot;작업 중인 파일이 있으니 커밋하거나 stash(임시 저장)하라&quot;고 에러를 뱉음. 하던 맥락을 끊고 git stash를 한 뒤 넘어가야 함.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Worktree 방식:&lt;/b&gt; 폴더 자체가 분리되어 있으므로 하던 작업을 저장하거나 커밋할 필요가 없음. main 폴더에 작업 중인 코드를 그대로 켜둔 채로, 그냥 옆 폴더(bugfix)로 이동해서 바로 코딩하면 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;15&quot; data-ke-size=&quot;size20&quot;&gt;2. 왜 Claude Code와 함께 쓸 때 강력할까?&lt;/h4&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 구조가 물리적으로 분리되기 때문에 완벽한 격리가 가능함.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;17&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,0,0&quot;&gt;인간과 AI의 작업 분리:&lt;/b&gt; 폴더 A(main 브랜치)에서는 내가 원래 하던 피처 개발을 진행하고, 동시에 폴더 B(feature 브랜치)를 새로 만들어 Claude Code에게 &quot;이 폴더 버그 좀 잡아줘&quot;라고 던져놓을 수 있음.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,1,0&quot;&gt;의존성 격리:&lt;/b&gt; Claude가 코드를 대대적으로 수정하면서 발생하는 빌드 깨짐이나 임시 파일들이 내 작업 공간에 전혀 영향을 주지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;19&quot; data-ke-size=&quot;size20&quot;&gt;3. Git Worktree 핵심 명령어&lt;/h4&gt;
&lt;h4 data-path-to-node=&quot;20&quot; data-ke-size=&quot;size20&quot;&gt;① 새로운 워크트리 생성&lt;/h4&gt;
&lt;p data-path-to-node=&quot;21&quot; data-ke-size=&quot;size16&quot;&gt;현재 프로젝트 폴더의 상위 경로에 새로운 폴더를 만들고, 새 브랜치를 연결하는 명령어.&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwjT3_7_u7iVAxUAAAAAHQAAAAAQ6QE&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;# 사용법: git worktree add [생성할 폴더 경로] -b [새 브랜치명]
$ git worktree add ../my-app-claude -b feature-claude-task

Preparing worktree (new branch 'feature-claude-task')
HEAD is now at a1b2c3d Initial commit
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;23&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 폴더 바로 바깥에 my-app-claude라는 물리적인 폴더가 실제로 생겨남.&lt;/li&gt;
&lt;li&gt;해당 폴더로 이동(cd ../my-app-claude)해 보면 브랜치가 자동으로 feature-claude-task로 전환되어 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;24&quot; data-ke-size=&quot;size20&quot;&gt;② 워크트리 목록 확인&lt;/h4&gt;
&lt;p data-path-to-node=&quot;25&quot; data-ke-size=&quot;size16&quot;&gt;현재 저장소에 연결된 워크트리 경로와 브랜치 목록을 확인&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwjT3_7_u7iVAxUAAAAAHQAAAAAQ6gE&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;$ git worktree list

/Users/developer/Desktop/my-app         a1b2c3d [main]
/Users/developer/Desktop/my-app-claude  a1b2c3d [feature-claude-task]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 data-path-to-node=&quot;27&quot; data-ke-size=&quot;size20&quot;&gt;③ 워크트리 삭제&lt;/h4&gt;
&lt;p data-path-to-node=&quot;28&quot; data-ke-size=&quot;size16&quot;&gt;AI가 작업을 끝내고 원격 저장소에 푸시(Push)까지 완료했다면 워크트리를 삭제함. &lt;b data-index-in-node=&quot;48&quot; data-path-to-node=&quot;28&quot;&gt;(반드시 원래 메인 프로젝트 폴더로 돌아와서 수행)&lt;/b&gt;&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwjT3_7_u7iVAxUAAAAAHQAAAAAQ6wE&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 메인 폴더로 이동 후 삭제
$ cd ../my-app
$ git worktree remove ../my-app-claude
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연결이 해제되면서 상위에 생성되었던 my-app-claude 폴더도 자동으로 삭제됨.&lt;/li&gt;
&lt;li&gt;.git 저장소 자체는 공유하고 있었기 때문에, 옆 폴더에서 작업하고 커밋했던 내역은 메인 폴더의 git log에서도 그대로 조회됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;32&quot; data-ke-size=&quot;size20&quot;&gt;요약&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;33&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;git worktree는 하나의 저장소를 공유하며 &lt;b data-index-in-node=&quot;28&quot; data-path-to-node=&quot;33,0,0&quot;&gt;여러 브랜치를 독립된 폴더로 동시에 펼쳐놓는 기능&lt;/b&gt;임.&lt;/li&gt;
&lt;li&gt;브랜치를 전환할 때 작업 내역을 stash하거나 기다릴 필요가 없음.&lt;/li&gt;
&lt;li&gt;이 격리 공간을 활용하면 &lt;b data-index-in-node=&quot;14&quot; data-path-to-node=&quot;33,2,0&quot;&gt;인간과 AI(Claude Code)가 서로의 컨텍스트를 깨뜨리지 않고 완벽한 병렬 작업&lt;/b&gt;을 수행할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;다음 글에서는 Claude Code의 내장 명령어(claude --worktree)를 활용해 이 과정을 한 줄로 자동화하는 방법을 알아볼 예정&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>claud code</category>
      <category>git worktree</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>워크트리</category>
      <category>클로드코드</category>
      <category>클로드코드 병렬</category>
      <category>클로드코드 효율</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1857</guid>
      <comments>https://ios-development.tistory.com/1857#entry1857comment</comments>
      <pubDate>Sun, 5 Jul 2026 17:26:31 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 5. 애플페이 (Apply Pay) - PassKit을 사용하여 구현하기 (Green, Yellow, Orange 플로우)</title>
      <link>https://ios-development.tistory.com/1856</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;font-size: 23.04px; letter-spacing: -1px;&quot;&gt;Green, Yellow, Orange 플로우&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;15&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;흐름 (Flow)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;진입 경로&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;리스크 수준&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;인증 절차&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;최종 상태&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0,0&quot;&gt;Green-Flow&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,1,1,0&quot;&gt;발급사 인앱 (In-App)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,1,2,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,2,0&quot;&gt;Low&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,1,3,0&quot;&gt;앱 로그인으로 대체&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,1,4,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,4,0&quot;&gt;즉시 활성화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,0,0&quot;&gt;Yellow-Flow&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,2,1,0&quot;&gt;Apple 월렛 직접 입력&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,2,2,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,2,0&quot;&gt;Medium&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,2,3,0&quot;&gt;발급사 앱 인증 / SMS / ARS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,2,4,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,4,0&quot;&gt;인증 후 활성화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,3,0,0&quot;&gt;Orange-Flow&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,3,1,0&quot;&gt;의심 기기 / 분실 카드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,3,2,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,3,2,0&quot;&gt;High&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,3,3,0&quot;&gt;없음 (거절 또는 강제 차단)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;15,3,4,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,3,4,0&quot;&gt;등록 실패&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;color: #000000; font-size: 1.44em; letter-spacing: -1px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;애플페이 (Issuer App 입장)의 기능&lt;/span&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;발급사(Issuer) 앱 관점에서 애플페이 대응을 할 때 핵심이 되는 개념은 크게 &lt;/span&gt;&lt;b data-index-in-node=&quot;46&quot; data-path-to-node=&quot;3&quot;&gt;In-App Provisioning&lt;/b&gt;&lt;span&gt;과 &lt;/span&gt;&lt;b data-index-in-node=&quot;67&quot; data-path-to-node=&quot;3&quot;&gt;Verification&lt;/b&gt;&lt;span&gt; 두 가지로 나뉨.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;4&quot; data-ke-size=&quot;size20&quot;&gt;1) In-App Provisioning (인앱 프로비저닝)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;개념:&lt;/b&gt;&lt;span&gt; 사용자가 우리 앱 내부에서 &quot;애플 월렛에 추가&quot; 버튼을 눌렀을 때,&lt;/span&gt;&lt;span&gt; 안전하게 카드 정보를 암호화하여 Apple Wallet에 카드를 밀어 넣어주는(발급하는) 기능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;특징:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;앱 내부에서 &lt;/span&gt;PKAddPaymentPassViewController&lt;span&gt;라는 Apple 표준 시트를 띄워 처리하므로 화면 이탈 없이 매끄러운 UX를 제공.&lt;/span&gt;&lt;span&gt; (Green-Flow)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;앱이 카드 번호(PAN) 원장을 가공되지 않은 상태로 다루지 않고,&lt;/span&gt;&lt;span&gt; 기기가 생성한 일회성 토큰(&lt;/span&gt;Nonce&lt;span&gt;)을 기반으로 발급사 백엔드와 TSP(Visa,&lt;/span&gt;&lt;span&gt; Mastercard 등)를 거쳐 암호화된 페이로드 형태로 Apple 서버에 패스스루(Pass-through)하는 구조.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size20&quot;&gt;2) Verification (신원 확인 및 인증)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;개념:&lt;/b&gt;&lt;span&gt; 반대로 사용자가 &lt;/span&gt;&lt;b data-index-in-node=&quot;13&quot; data-path-to-node=&quot;7,0,0&quot;&gt;애플 월렛 앱 안에서 직접 카드를 추가&lt;/b&gt;&lt;span&gt;하려고 할 때,&lt;/span&gt;&lt;span&gt; &quot;이 사람이 진짜 실소유주가 맞는지 확인해라&quot;라며 월렛이 발급사 앱을 깨워 본인 인증을 요구하는 기능.&lt;/span&gt;&lt;span&gt; (Yellow-Flow)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;특징:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,1,0,0&quot;&gt;Step-up Authentication&lt;/b&gt;&lt;span&gt;이라고도 부르며,&lt;/span&gt;&lt;span&gt; 유니버설 링크(Universal Link)를 통해 월렛 앱에서 우리 앱으로 사용자를 전환시킴.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우리 앱이 켜지면 Face ID나 간편비밀번호 등으로 본인 확인을 수행한 뒤,&lt;/span&gt;&lt;span&gt; 발급사 백엔드를 통해 TSP에 &quot;인증 완료&quot; 신호를 쏘고 다시 &lt;/span&gt;shoebox://&lt;span&gt; 스킴을 통해 사용자를 월렛으로 안전하게 돌려보내 줌.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;9&quot; data-ke-size=&quot;size23&quot;&gt;PassKit을 사용하여 구현하기&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-path-to-node=&quot;11&quot; data-ke-size=&quot;size20&quot;&gt;Step 0. 권한 설정&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;10&quot;&gt;1) PKPassLibrary: 애플월렛관련 데이터를 가져오기 위한 라이브러리이고 애플 개발자 페이지의 capability에서 &lt;b&gt;Wallet&lt;/b&gt; 활성화해야함&lt;/li&gt;
&lt;li data-path-to-node=&quot;10&quot;&gt;2) 애플 in-app provisioining 권한
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;10&quot;&gt;PKAddPaymentPassViewController를 사용하려면 애플 개발자 페이지 -&amp;gt; Capability -&amp;gt; In-App Provisioning 권한이 필요&lt;/li&gt;
&lt;li data-path-to-node=&quot;10&quot;&gt;Xcode에서도 entitlements 파일에 아래 설정도 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1782657687854&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// {your_app}.entitlements

&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;com.apple.developer.passkit.in-app-provisioning&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
&amp;lt;/dict&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-path-to-node=&quot;11&quot; data-ke-size=&quot;size20&quot;&gt;Step 1. 권한 확인 및 Configuration 설정&lt;/h4&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;가장 먼저 현재 디바이스가 카드 등록을 지원하는지 체크하고, 카드 소유자 이름 및 뒤 4자리 정보를 담은 설정을 빌드&lt;/p&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;*주의) PKAddPaymentPassViewController를 사용하려면 애플 개발자 페이지 -&amp;gt; Capability -&amp;gt; In-App Provisioning 권한이 필요&amp;nbsp;&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwifpub3k6qVAxUAAAAAHQAAAAAQ2AI&quot; data-hveid=&quot;0&quot;&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;import PassKit

func startInAppProvisioning() {
    // 1. 디바이스가 인앱 프로비저닝을 지원하는지 체크
    guard PKAddPaymentPassViewController.canAddPaymentPass() else {
        print(&quot;이 디바이스는 카드 추가를 지원하지 않거나 제한된 계정임&quot;)
        return
    }
    
    // 2. 발급할 카드의 메타데이터 구성 (암호화 스킴은 보통 ECC_V2 또는 RSA_V2 사용)
    guard let configuration = PKAddPaymentPassRequestConfiguration(encryptionScheme: .ECC_V2) else {
        return
    }
    
    configuration.cardholderName = &quot;홍길동&quot;
    configuration.primaryAccountSuffix = &quot;1234&quot; // 카드 뒷 4자리
    configuration.localizedDescription = &quot;내 발급사 대표 카드&quot;
    
    // 3. VC 생성 및 델리게이트 위임
    guard let addPaymentPassVC = PKAddPaymentPassViewController(requestConfiguration: configuration, delegate: self) else {
        print(&quot;컨트롤러 생성 실패 - Entitlement 권한 확인 필요&quot;)
        return
    }
    
    // 4. Apple 표준 카드 등록 시트 모달 표시
    self.present(addPaymentPassVC, animated: true, completion: nil)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size20&quot;&gt;Step 2. PKAddPaymentPassViewControllerDelegate 구현&lt;/h4&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;시트가 뜨면 Apple 서버-발급사 서버 간 암호화 핸드셰이크가 일어남. 이 구간이 구현의 핵심&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwifpub3k6qVAxUAAAAAHQAAAAAQ2QI&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;extension CardManagementViewController: PKAddPaymentPassViewControllerDelegate {
    
    // Apple 이 인증서 체인과 Nonce 를 넘겨주며 암호화 데이터를 요청하는 메서드
    func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController,
                                      generateRequestWithCertificateChain certificates: [Data],
                                      nonce: Data,
                                      nonceSignature: Data,
                                      completionHandler: @escaping (PKAddPaymentPassRequest) -&amp;gt; Void) {
        
        // 1. 수신한 certificates, nonce, nonceSignature 를 우리 백엔드 API 로 전송
        let requestModel = IssuerAmhohwaRequest(
            certificates: certificates,
            nonce: nonce,
            nonceSignature: nonceSignature
        )
        
        // 2. 백엔드 통신 (백엔드는 TSP 와 연동하여 암호화된 데이터를 내려줌)
        NetworkManager.shared.requestEncryptedPayload(requestModel) { result in
            switch result {
            case .success(let response):
                // 3. 백엔드가 준 데이터를 암호화 요청 객체에 매핑
                let addPassRequest = PKAddPaymentPassRequest()
                addPassRequest.encryptedPassData = response.encryptedPassData
                addPassRequest.activationData = response.activationData
                addPassRequest.ephemeralPublicKey = response.ephemeralPublicKey
                
                // 4. 완성된 request 를 completionHandler 에 담아 Apple SDK 에 반환
                completionHandler(addPassRequest)
                
            case .failure:
                // 에러 발생 시 빈 객체를 던져 실패 처리
                completionHandler(PKAddPaymentPassRequest())
            }
        }
    }
    
    // 프로세스가 완전히 끝났을 때 (성공 혹은 취소/실패) 호출되는 메서드
    func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController,
                                      didFinishWith pass: PKPaymentPass?,
                                      error: Error?) {
        // 우선 띄웠던 모달을 닫아줌
        controller.dismiss(animated: true) {
            if let error = error {
                print(&quot;카드 등록 실패 혹은 유저 취소 발생: \(error.localizedDescription)&quot;)
                return
            }
            
            if let successfullyAddedPass = pass {
                print(&quot;카드 등록 최종 성공: \(successfullyAddedPass.primaryAccountNumberSuffix)&quot;)
                // UI 상의 '애플 월렛에 추가' 버튼을 숨기거나 완료 상태로 전환하는 비즈니스 로직 수행
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>apple pay</category>
      <category>ApplePay</category>
      <category>ios</category>
      <category>PassKit</category>
      <category>SWIFT</category>
      <category>애플페이</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1856</guid>
      <comments>https://ios-development.tistory.com/1856#entry1856comment</comments>
      <pubDate>Mon, 29 Jun 2026 00:34:45 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] 4. 애플페이 (Apply Pay) - 애플월렛과 앱에서 카드등록 개념</title>
      <link>https://ios-development.tistory.com/1855</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;애플페이 관련 목차&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://ios-development.tistory.com/1854&quot;&gt;전체 목차 링크&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style3&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;대응해야하는 영역&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내앱에서 애플페이 결제는 지원하지 않고, 내앱에 있는 카드 정보를 애플월렛에 등록하여 애플월렛에서 결제하게끔 도와주는 방법을 대상으로 설명 예정 (Issuer App 관점)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 진입점이 애플월렛&lt;/b&gt;: 애플월렛 -&amp;gt; 내앱(Issuer App) -&amp;gt; 애플월렛&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 애플월렛 앱에서 직접 카드를 추가(실물 카드 카메라 스캔 또는 번호 직접 입력)하는 도중, &quot;이 사람이 진짜 카드 주인이 맞는지 발급사 앱에서 인증해라&quot;라고 요청받아 넘어오는 플로우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;핵심 메커니즘:&lt;/b&gt; 유니버설 링크를 통한 신원 확인 (Step-up Authentication)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;흐름:&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;9,1,1&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;애플월렛이 발급사의 &lt;b data-index-in-node=&quot;11&quot; data-path-to-node=&quot;9,1,1,0,0&quot;&gt;유니버설 링크&lt;/b&gt;를 호출하여 발급사 앱을 강제로 깨움.&lt;/li&gt;
&lt;li&gt;발급사 앱이 켜지면서 URL에 담긴 토큰 정보를 파싱하고, 사용자에게 &lt;b data-index-in-node=&quot;39&quot; data-path-to-node=&quot;9,1,1,1,0&quot;&gt;Face ID 또는 간편비밀번호 인증&lt;/b&gt;을 요구.&lt;/li&gt;
&lt;li&gt;인증이 성공하면 발급사 백엔드가 TSP(카드 브랜드사)에 &quot;인증 완료&quot; 신호를 보냄.&lt;/li&gt;
&lt;li&gt;앱이 shoebox:// 스킴을 호출하여 사용자를 다시 애플월렛으로 돌려보냄.&lt;br /&gt;* shoebox 앱스킴: Apple Wallet(애플월렛) 앱을 호출하기 위해 Apple이 전 세계 모든 개발사에게 공식적으로 지정해 둔 실제 프로덕션용 URL 스킴&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;특징:&lt;/b&gt; 앱과 앱 사이를 전환(애플월렛 ➔ 발급사 앱 ➔ 애플월렛)하며 흐름이 이어짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdTN4u/dJMcada8MGy/yQBKDWUBXBFULxHysKh76K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdTN4u/dJMcada8MGy/yQBKDWUBXBFULxHysKh76K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdTN4u/dJMcada8MGy/yQBKDWUBXBFULxHysKh76K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdTN4u%2FdJMcada8MGy%2FyQBKDWUBXBFULxHysKh76K%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;1566&quot; height=&quot;956&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 진입점이 내앱&lt;/b&gt;: 내앱(Issuer App) -&amp;gt; 애플월렛&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,0,0&quot; data-index-in-node=&quot;0&quot;&gt;발급사 앱 안에서 사용자가 &quot;애플 월렛에 추가&quot; 버튼을 눌러 카드를 등록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,0,0&quot; data-index-in-node=&quot;0&quot;&gt;핵심 메커니즘:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;암호화 데이터 토싱 (Pass-Through)&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,1,0&quot; data-index-in-node=&quot;0&quot;&gt;흐름&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1. 앱에서 Apple 표준 등록 시트(PKAddPaymentPassViewController)를 띄움.&lt;/li&gt;
&lt;li&gt;2. 기기가 생성한 일회성 암호화 키(Nonce)를 발급사 앱이 받아서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b data-path-to-node=&quot;6,1,0&quot; data-index-in-node=&quot;103&quot;&gt;발급사 백엔드&lt;/b&gt;로 전달.&lt;/li&gt;
&lt;li&gt;3. 백엔드가 카드 정보와 Nonce를 결합해 암호화된 페이로드(Payload)를 만들어 앱으로 반환.&lt;/li&gt;
&lt;li&gt;4. 앱이 이 페이로드를 그대로 Apple 서버에 제출하면 카드 등록 완료.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;6,2,0&quot; data-index-in-node=&quot;0&quot;&gt;특징:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;화면 전환 없이 발급사 앱 안에서 모달 시트 형태로 매끄럽게 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boLWJS/dJMcageIehe/b6Xx8FtNYl8fdPKSkZxr5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boLWJS/dJMcageIehe/b6Xx8FtNYl8fdPKSkZxr5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boLWJS/dJMcageIehe/b6Xx8FtNYl8fdPKSkZxr5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboLWJS%2FdJMcageIehe%2Fb6Xx8FtNYl8fdPKSkZxr5K%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;1396&quot; height=&quot;1000&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;두 방식의 차이&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 차이는 &lt;b data-index-in-node=&quot;9&quot; data-path-to-node=&quot;12&quot;&gt;카드 정보(원장)의 출발지&lt;/b&gt;와 &lt;b data-index-in-node=&quot;25&quot; data-path-to-node=&quot;12&quot;&gt;UI 주도권&lt;/b&gt;이 누구에게 있느냐&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;13&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;비교 항목&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;  내 앱에서 시작 (Green-Flow)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;  애플월렛에서 시작 (Yellow-Flow)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,0,0&quot;&gt;주도권 (시작점)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,1,1,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,1,0&quot;&gt;Issuer App (발급사 앱)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,1,2,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,2,0&quot;&gt;Apple Wallet (애플월렛 앱)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,2,0,0&quot;&gt;카드 정보 입력&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,2,1,0&quot;&gt;필요 없음 (앱 내부 카드 목록에서 선택)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,2,2,0&quot;&gt;필요함 (사용자가 직접 입력 또는 카메라 스캔)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,3,0,0&quot;&gt;핵심 기술 요소&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,3,1,0&quot;&gt;PassKit 프레임워크 델리게이트 구현&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,3,2,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,3,2,0&quot;&gt;Universal Link&lt;/b&gt; 및 URL Scheme (shoebox://)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,4,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,4,0,0&quot;&gt;보안 작업의 본질&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,4,1,0&quot;&gt;안전하게 카드 정보를 암호화하여 Apple에 전달&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,4,2,0&quot;&gt;사용자가 본인이 맞는지 생체인증 등으로 검증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,5,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,5,0,0&quot;&gt;화면 경험 (UX)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,5,1,0&quot;&gt;발급사 앱 내부에서 모달 창으로 해결&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;13,5,2,0&quot;&gt;앱 간의 유기적인 스위칭 (App-to-App)&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;</description>
      <category>iOS 응용 (swift)</category>
      <category>apple pay</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>Xcode</category>
      <category>애플페이</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1855</guid>
      <comments>https://ios-development.tistory.com/1855#entry1855comment</comments>
      <pubDate>Wed, 17 Jun 2026 01:35:36 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 애플페이 목차</title>
      <link>https://ios-development.tistory.com/1854</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;애플페이 관련 목차&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://ios-development.tistory.com/1852&quot;&gt;애플페이 (Apply Pay) - 처리해야하는 전체 플로우&lt;/a&gt;&lt;br /&gt;2. &lt;a href=&quot;https://ios-development.tistory.com/1851&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플페이 (Apply Pay) - 사전 설정 2단계 (앱 외적인 세팅)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #99cefa;&quot;&gt;&lt;a style=&quot;color: #99cefa;&quot; href=&quot;https://ios-development.tistory.com/1853&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;애플페이 (Apply Pay) - Xcode에 적용하기&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;4. &lt;a href=&quot;https://ios-development.tistory.com/1855&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플페이&amp;nbsp;(Apply&amp;nbsp;Pay)&amp;nbsp;-&amp;nbsp;애플월렛과&amp;nbsp;앱에서&amp;nbsp;카드등록&amp;nbsp;개념&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;5. &lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://ios-development.tistory.com/1856&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플페이 (Apply Pay) - PassKit을 사용하여 구현하기&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1854</guid>
      <comments>https://ios-development.tistory.com/1854#entry1854comment</comments>
      <pubDate>Wed, 10 Jun 2026 01:29:29 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] 3. 애플페이 (Apply Pay) - Xcode에 적용하기</title>
      <link>https://ios-development.tistory.com/1853</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;애플페이 관련 목차&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ios-development.tistory.com/1854&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;전체 목차 링크&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style3&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Xcode에 적용하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode &amp;gt; Project &amp;gt; Signing &amp;amp; Capabilities
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;+ Capability를 클릭&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2610&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/maHLL/dJMcagZTfqV/MF98vBk1gzGKf4zt4iTvgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/maHLL/dJMcagZTfqV/MF98vBk1gzGKf4zt4iTvgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/maHLL/dJMcagZTfqV/MF98vBk1gzGKf4zt4iTvgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmaHLL%2FdJMcagZTfqV%2FMF98vBk1gzGKf4zt4iTvgk%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;2610&quot; height=&quot;1026&quot; data-origin-width=&quot;2610&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Apply Pay 검색&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;1008&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CK44R/dJMcadaZGBs/kyX7VoLs53K3T6YfKzeBu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CK44R/dJMcadaZGBs/kyX7VoLs53K3T6YfKzeBu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CK44R/dJMcadaZGBs/kyX7VoLs53K3T6YfKzeBu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCK44R%2FdJMcadaZGBs%2FkyX7VoLs53K3T6YfKzeBu0%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;1848&quot; height=&quot;1008&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;1008&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색했을때 아무것도 안뜬다면, 애플 개발자 페이지에서 애플페이를 추가해줘야함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단 애플 개발자 구독 플랜이 되어있어야함 (연간 99$ 애플 구독)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;882&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUqWGB/dJMcaiJ94sN/JqQWZNWLrNhDMsDHYNMmjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUqWGB/dJMcaiJ94sN/JqQWZNWLrNhDMsDHYNMmjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUqWGB/dJMcaiJ94sN/JqQWZNWLrNhDMsDHYNMmjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUqWGB%2FdJMcaiJ94sN%2FJqQWZNWLrNhDMsDHYNMmjK%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;1848&quot; height=&quot;882&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;882&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;애플 개발자 페이지에서 애플페이 활성화하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Apple Developer 웹사이트 로그인:&amp;nbsp;&lt;a href=&quot;https://developer.apple.com/&quot;&gt;Apple Developer 계정 페이지&lt;/a&gt;에 로그인한 뒤, Certificates, Identifiers &amp;amp; Profiles 메뉴로 이동&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Identifiers에서 앱 선택:&amp;nbsp;왼쪽 메뉴의 Identifiers를 누르고, 현재 작업 중인 프로젝트의 Bundle ID를 찾아 클릭&lt;/li&gt;
&lt;li&gt;Apple Pay 기능 활성화: Capabilities 리스트 중에서 Apple Pay Payment Processing 항목을 찾아 체크박스를 선택(Enable)하고 Save를 눌러 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;다시 XCode &amp;gt; Capability 눌러서 시도하면 Apple Pay가 보이는 것을 확인 가능&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;882&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eLBnwR/dJMcabYD4Zf/5MQqI2hhYWVE2DhQSFzDIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eLBnwR/dJMcabYD4Zf/5MQqI2hhYWVE2DhQSFzDIK/img.png&quot; data-alt=&quot;https://apnspush.com/integrate-apple-pay-into-ios-app&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eLBnwR/dJMcabYD4Zf/5MQqI2hhYWVE2DhQSFzDIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeLBnwR%2FdJMcabYD4Zf%2F5MQqI2hhYWVE2DhQSFzDIK%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;1354&quot; height=&quot;882&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;882&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://apnspush.com/integrate-apple-pay-into-ios-app&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그럼 아래처럼 Merchant ID 입력 화면이 등장
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #777777; text-align: center;&quot;&gt;Merchant ID는 &lt;a href=&quot;https://ios-development.tistory.com/1851&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이전 글&lt;/a&gt; 참고 (단, 애플월렛에 단순히 카드등록만 하는 경우는 &quot;Issuer App&quot;이라 하며 Merchant ID는 필요없음.)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;866&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xz6dr/dJMcajbblYw/k6sx14NSLck1isgvrFZ7aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xz6dr/dJMcajbblYw/k6sx14NSLck1isgvrFZ7aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xz6dr/dJMcajbblYw/k6sx14NSLck1isgvrFZ7aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXz6dr%2FdJMcajbblYw%2Fk6sx14NSLck1isgvrFZ7aK%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;1366&quot; height=&quot;866&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;866&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력 시 아래처럼 merchant id들이 추가됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ds4Rb/dJMcadhQzM7/mrGwy5kjuJ47Mf5Ehk3hh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ds4Rb/dJMcadhQzM7/mrGwy5kjuJ47Mf5Ehk3hh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ds4Rb/dJMcadhQzM7/mrGwy5kjuJ47Mf5Ehk3hh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDs4Rb%2FdJMcadhQzM7%2FmrGwy5kjuJ47Mf5Ehk3hh1%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;1426&quot; height=&quot;358&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 apple pay를 만들 준비가 끝났고, 다음 글에서 PassKit을 사용하여 애플페이 구현을 계속 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;color: #777777; text-align: center;&quot;&gt;&lt;a href=&quot;https://apnspush.com/integrate-apple-pay-into-ios-app&quot;&gt;https://apnspush.com/integrate-apple-pay-into-ios-app&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>apple pay</category>
      <category>applypay</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>애플페이</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1853</guid>
      <comments>https://ios-development.tistory.com/1853#entry1853comment</comments>
      <pubDate>Wed, 10 Jun 2026 01:16:36 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] 2. 애플페이 (Apply Pay) - 사전 설정 2단계 (앱 외적인 세팅)</title>
      <link>https://ios-development.tistory.com/1851</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;애플페이 관련 목차&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://ios-development.tistory.com/1854&quot;&gt;전체 목차 링크&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot;&gt;사전 설정&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot;&gt;Apple Pay 결제 데이터의 암호화 키체인을 구성&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSBTgu/dJMcahEpH5K/GHZhKKFezTnCSF57pDJx6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSBTgu/dJMcahEpH5K/GHZhKKFezTnCSF57pDJx6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSBTgu/dJMcahEpH5K/GHZhKKFezTnCSF57pDJx6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSBTgu%2FdJMcahEpH5K%2FGHZhKKFezTnCSF57pDJx6K%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;1188&quot; height=&quot;332&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;1단계) Merchant id 만들기&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Merchant id (판매자 식별자)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Merchant id는&lt;/span&gt;&lt;span style=&quot;color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Apple Pay에서 결제를 받을 수 있는 판매자임을 고유하게 식별하는 데 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;판매자 식별자는 만료되지 않으며 여러 앱에서 동일한 식별자를 사용할 수 있음&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #1d1d1f; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0066cc;&quot; href=&quot;https://developer.apple.com/account/resources&quot;&gt;인증서, 식별자 및 프로필&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서사이드바에서 '식별자'를 클릭한 다음 왼쪽 상단의 추가 버튼(+)을 클릭&lt;/li&gt;
&lt;li&gt;판매자 ID를 선택한 다음 계속을 클릭&lt;/li&gt;
&lt;li&gt;판매자 설명과 식별자 이름을 입력한 다음 계속을 클릭&lt;/li&gt;
&lt;li&gt;설정을 검토한 후 등록을 클릭&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2단계) payment processing certificate 만들기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;payment processing certificate (결제 처리 인증서)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결제 처리 인증서는&lt;span style=&quot;color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;판매자&lt;/span&gt;&lt;span style=&quot;color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;식별자와 연결되어 있으며 결제 정보를 암호화하는 데 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;결제 처리 인증서는 25개월마다 만료&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;인증서가 취소된 경우 재발급받을 수 있음&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&quot;create-a-payment-processing-certificate&quot; style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0066cc;&quot; href=&quot;https://developer.apple.com/account/resources&quot;&gt;인증서, 식별자 및 프로필&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서 사이드바에서 '식별자'를 클릭&lt;/li&gt;
&lt;li&gt;&lt;span&gt;식별자 항목에서 오른쪽&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상단의 필터를 사용하여 판매자 ID를 선택&lt;/li&gt;
&lt;li&gt;&lt;span&gt;오른쪽&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;판매자 식별자를 선택 &lt;br /&gt;&lt;b&gt;참고:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;페이지 상단에 이용약관에 동의해야 한다는 배너가 표시되면 '이용약관 검토' 버튼을 클릭하고 안내에 따라 진행&lt;/li&gt;
&lt;li&gt;Apple Pay 결제 처리 인증서 아래에서 인증서 생성을 클릭&lt;/li&gt;
&lt;li&gt;Mac에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0066cc;&quot; href=&quot;https://developer.apple.com/help/account/certificates/create-a-certificate-signing-request&quot;&gt;인증서 서명 요청을 생성한 다음 계속을 클릭.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;파일 선택을 클릭&lt;/li&gt;
&lt;li&gt;나타나는 대화 상자에서 인증서 요청 파일(파일 확장자가 있는 파일&lt;span&gt;&amp;nbsp;&lt;/span&gt;.certSigningRequest)을 선택한 다음 [선택]을 클릭&lt;/li&gt;
&lt;li&gt;계속을 클릭&lt;/li&gt;
&lt;li&gt;다운로드를 클릭&lt;/li&gt;
&lt;li&gt;인증서 파일(파일 확장자가 있는 파일&lt;span&gt;&amp;nbsp;&lt;/span&gt;.cer)이&lt;span&gt;&amp;nbsp;&lt;/span&gt;Downloads폴더에 나타남&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/documentation/passkit/apple-pay&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/documentation/passkit/apple-pay&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/help/account/capabilities/configure-apple-pay#create-a-merchant-identifier&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/help/account/capabilities/configure-apple-pay#create-a-merchant-identifier&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/apple-pay/implementation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/apple-pay/implementation/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/documentation/passkit/setting-up-apple-pay&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/documentation/passkit/setting-up-apple-pay&lt;/a&gt;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>Apply Pay</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>애플페이</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1851</guid>
      <comments>https://ios-development.tistory.com/1851#entry1851comment</comments>
      <pubDate>Wed, 27 May 2026 01:08:49 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] 1. 애플페이 (Apply Pay) - 처리해야하는 전체 플로우</title>
      <link>https://ios-development.tistory.com/1852</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;애플페이 관련 목차&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://ios-development.tistory.com/1854&quot;&gt;전체 목차 링크&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #1d1d1f;&quot;&gt;애플페이을 준비하는 앱 개념&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Issuer App vs Merchant App
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Issuer App: 단순히 특정 A앱에서 카드들을 애플월렛에 등록하는 역할 (provisioning 이라고 함)&lt;/li&gt;
&lt;li&gt;Merchant App: A앱에서 애플페이를 이용한 결제기능을 제공하는 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;중요한 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Issuer App은 Apple Develop페이지에서 Pass Type ID 등록만하면 됨&lt;/li&gt;
&lt;li&gt;Merchant App은 Apple Develop페이지에서 Merchant ID 등록, CSR 업로드, App ID 등록을 해줘야함 (아래에서 소개 예정)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;처리해야하는 전체 플로우&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1d1f; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6BtE0/dJMcaiDlOMw/UtmI0idPug6EVydQK3chlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6BtE0/dJMcaiDlOMw/UtmI0idPug6EVydQK3chlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6BtE0/dJMcaiDlOMw/UtmI0idPug6EVydQK3chlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6BtE0%2FdJMcaiDlOMw%2FUtmI0idPug6EVydQK3chlk%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;1710&quot; height=&quot;754&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;2&quot; data-ke-size=&quot;size20&quot;&gt;1단계: Apple Developer 인프라 설정&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vEZKi/dJMcaiwzMjg/DUjFWSKnLeUQM08cnc66ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vEZKi/dJMcaiwzMjg/DUjFWSKnLeUQM08cnc66ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vEZKi/dJMcaiwzMjg/DUjFWSKnLeUQM08cnc66ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvEZKi%2FdJMcaiwzMjg%2FDUjFWSKnLeUQM08cnc66ck%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;1188&quot; height=&quot;332&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Apple Pay 결제 데이터의 암호화 키체인을 구성하는 단계&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #1f1f1f; text-align: start;&quot; data-path-to-node=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;Merchant ID (판매자 식별자) 생성:&lt;/b&gt;&lt;span&gt; 우리 앱이 Apple Pay 시스템에서 결제를 요청할 수 있는 고유한 상점 ID(&lt;/span&gt;merchant.com.domain...&lt;span&gt;)를 등록하는 과정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;Payment Processing Certificate (결제 처리 인증서) 생성:&lt;/b&gt;&lt;span&gt; 사용자가 페이스 ID 등으로 인증하면 Apple 서버는 결제 정보를 암호화.&lt;/span&gt;&lt;span&gt; 이때 암호화에 사용되는 공개키(Public Key)를 Apple에 등록하고,&lt;/span&gt;&lt;span&gt; 이를 복호화할 수 있는 &lt;/span&gt;&lt;b data-index-in-node=&quot;149&quot; data-path-to-node=&quot;4,1,0&quot;&gt;개인키(Private Key)&lt;/b&gt;&lt;span&gt; 쌍을 만드는 과정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size20&quot;&gt;2단계: 결제 대행사(PG) 연동 및 환경 설정&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yoRo9/dJMcabxrDSv/81skIjjZRkp5d0n9RvMsK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yoRo9/dJMcabxrDSv/81skIjjZRkp5d0n9RvMsK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yoRo9/dJMcabxrDSv/81skIjjZRkp5d0n9RvMsK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyoRo9%2FdJMcabxrDSv%2F81skIjjZRkp5d0n9RvMsK1%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;1236&quot; height=&quot;354&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;Apple Pay 결제 데이터를 복호화하고 실제 원화(KRW) 결제 승인을 처리할 PG사 연동 단계&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;PG사 선정 및 계약:&lt;/b&gt; 토스페이먼츠, 포트원, NHN KCP, KG이니시스 등 Apple Pay 지원 국내 PG사 선택 및 가맹 계약 진행&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;인증서 업로드:&lt;/b&gt; 1단계에서 생성한 Payment Processing Certificate(.cer 파일)를 PG사 상점 관리자 콘솔에 등록&lt;/li&gt;
&lt;li data-path-to-node=&quot;8,1,1&quot;&gt;  &lt;b data-index-in-node=&quot;3&quot; data-path-to-node=&quot;8,1,1,0&quot;&gt;등록 이유:&lt;/b&gt; Apple 서버가 암호화하여 앱으로 전송한 결제 데이터(Token)를 PG사가 복호화할 수 있도록 권한을 위임하는 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size20&quot;&gt;3단계: Xcode 프로젝트 개발 환경 설정&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1496&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTG9zp/dJMcaaZCnOv/0QJPNKCTgCuW9n95Hmhdy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTG9zp/dJMcaaZCnOv/0QJPNKCTgCuW9n95Hmhdy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTG9zp/dJMcaaZCnOv/0QJPNKCTgCuW9n95Hmhdy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTG9zp%2FdJMcaaZCnOv%2F0QJPNKCTgCuW9n95Hmhdy1%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;1496&quot; height=&quot;174&quot; data-origin-width=&quot;1496&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;생성한 Merchant ID를 Xcode 프로젝트와 동기화하여 앱에 Apple Pay 권한을 부여하는 단계&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;Apple Pay Capability 추가:&lt;/b&gt; Xcode 프로젝트의 Signing &amp;amp; Capabilities 탭에서 + Capability 버튼을 통해 &lt;b data-index-in-node=&quot;84&quot; data-path-to-node=&quot;12,0,0&quot;&gt;Apple Pay&lt;/b&gt; 기능 추가&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;Merchant ID 매핑:&lt;/b&gt; 추가된 Apple Pay 섹션의 &lt;b data-index-in-node=&quot;34&quot; data-path-to-node=&quot;12,1,0&quot;&gt;새로고침( ) 버튼&lt;/b&gt;을 클릭하여 생성해 둔 ID를 동기화하고 해당 체크박스 선택
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;완료 시 프로젝트 내 [프로젝트명].entitlements 파일이 자동 생성/업데이트되며 Apple Pay 권한이 명시됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size20&quot;&gt;4단계: 앱 내 결제 로직 구현 (코드 작성)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1776&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dy8joZ/dJMcagS5HHj/k2j9ZFjqAtRC9jODnLKaT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dy8joZ/dJMcagS5HHj/k2j9ZFjqAtRC9jODnLKaT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dy8joZ/dJMcagS5HHj/k2j9ZFjqAtRC9jODnLKaT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdy8joZ%2FdJMcagS5HHj%2Fk2j9ZFjqAtRC9jODnLKaT0%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;1776&quot; height=&quot;168&quot; data-origin-width=&quot;1776&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;사용자 결제 버튼 클릭부터 Apple Pay 시트 인증 및 최종 결제 완료까지의 클라이언트 코드 구현 단계 (PassKit 프레임워크 활용)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;16&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,0,0&quot;&gt;PG사 iOS SDK 설치:&lt;/b&gt; SPM 또는 CocoaPods를 통해 선택한 PG사의 최신 iOS SDK를 프로젝트에 추가&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,1,0&quot;&gt;Apple Pay 전용 버튼 배치:&lt;/b&gt; Apple 디자인 가이드라인을 준수하는 내장 이니셜라이저 기반의 PKPaymentButton을 UI에 배치&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,2,0&quot;&gt;결제 요청서(PKPaymentRequest) 정의:&lt;/b&gt; Merchant ID, 국가 코드(KR), 통화 코드(KRW), 지원 카드 브랜드 목록 지정 및 결제 금액 목록(PKPaymentSummaryItem) 구성 (배열의 마지막 아이템이 최종 결제 총액)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,3,0&quot;&gt;결제 시트 표시 및 델리게이트 구현:&lt;/b&gt; PKPaymentAuthorizationController를 통해 화면 하단에 Apple Pay 결제 시트 노출 및 사용자 인증 처리&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,4,0&quot;&gt;토큰 추출 및 PG사 전달:&lt;/b&gt; didAuthorizePayment 콜백 메서드로 전달된 PKPayment 객체에서 암호화된 결제 데이터(payment.token.paymentData)를 추출하여 PG사 결제 승인 API로 전송&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;16,5,0&quot;&gt;결제 결과 처리:&lt;/b&gt; PG사 서버의 최종 결제 승인 결과에 따라 Apple Pay 시트에 성공/실패 애니메이션을 표시하고 시트 종료(dismiss)&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;background-color: #ffffff; color: #5c5c5c; text-align: start;&quot;&gt;
&lt;p style=&quot;color: #555555;&quot; data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p style=&quot;color: #555555;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/passkit/apple-pay&quot;&gt;https://developer.apple.com/documentation/passkit/apple-pay&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/help/account/capabilities/configure-apple-pay#create-a-merchant-identifier&quot;&gt;https://developer.apple.com/help/account/capabilities/configure-apple-pay#create-a-merchant-identifier&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/kr/apple-pay/implementation/&quot;&gt;https://developer.apple.com/kr/apple-pay/implementation/&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/documentation/passkit/setting-up-apple-pay&quot;&gt;https://developer.apple.com/documentation/passkit/setting-up-apple-pay&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>Apply Pay</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>애플페이</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1852</guid>
      <comments>https://ios-development.tistory.com/1852#entry1852comment</comments>
      <pubDate>Wed, 20 May 2026 01:15:54 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 사용 종류 (인증 방식, session key, API Key, Amazon Bedrock)</title>
      <link>https://ios-development.tistory.com/1850</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드코드 사용 종류&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클로드코드를 사용할때 클로드코드에 비용을 지불하고 사용하는데 여러가지 방법이 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;session key - 개인이 가장 많이 사용 (구독해서 사용하는 것. 구체적인 건 아래에서 계속 설명)&lt;/li&gt;
&lt;li&gt;API key&lt;/li&gt;
&lt;li&gt;Amazon Bedrock&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;session key 방식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;session key: 넷플릭스나 유튜브 프리미엄을 구독해서 쓰는 것과 비슷하게 claude auth login을 치고 웹브라우저에서 로그인
&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;구독하여 사용하는 것이 session key 방식: &lt;b&gt;ex)&lt;/b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;월&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;$20 (Pro&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;구독&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클로드코드 설치하여 session key 방식 준비&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1778391258617&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -fsSL https://claude.ai/install.sh | bash&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 명령어를 통해 웹사이트에 로그인 및 구독 플랜을 선택한 후 결제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1778391252622&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;claude auth login&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잘 연결 되었는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1778391357052&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;claude auth status&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;API key 방식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Anthropic이 발행해준 &lt;b data-index-in-node=&quot;58&quot; data-path-to-node=&quot;4&quot;&gt;고유한 문자열 코드&lt;/b&gt;를 사용하는 것&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://console.anthropic.com/&quot; data-ved=&quot;0CAAQ_4QMahgKEwj93Pen9K2UAxUAAAAAHQAAAAAQ9QE&quot; data-hveid=&quot;0&quot;&gt;Anthropic Console&lt;/a&gt;에서 키를 생성하여 Claude Code에 claude auth apikey &amp;lt;내-키&amp;gt;를 입력해 등록&lt;/li&gt;
&lt;li&gt;쓴만큼 결제하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Amazon&amp;nbsp;Bedrock&lt;/h4&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;클로드코드에 바로 접근해서 쓰는게 아니라, aws를 통해 사용하는방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Bedrock은 Converse API가 아니라 Invoke API 경로를 사용&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;=&amp;gt; 표준화된 공통 문(Converse)이 아니라, Claude 모델 전용 문(Invoke)으로 직접 들어가서 대화&lt;/li&gt;
&lt;li&gt;데이터 형식을 더 꼼꼼히 맞춰줘야 하지만, 모델이 가진 원래의 성능이나 특수한 기능을 더 정확하게 끌어낼 수 있다는 장점이 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 각 모델마다 아래처럼 사용 방식이 다른데, Amazon Bedrock을 쓰면 aws에서 내부적으로 세팅하여, 사용자는 따로 신경쓰지 않아도됨&lt;/p&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;Claude (Anthropic 방식)&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;클로드에게 보낼 때는 messages라는 항목 안에 role과 content를 명확히 나누는 것을 선호&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwj93Pen9K2UAxUAAAAAHQAAAAAQuAE&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;model&quot;: &quot;claude-3-5-sonnet&quot;,
  &quot;messages&quot;: [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;안녕?&quot;}
  ],
  &quot;max_tokens&quot;: 1024
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9&quot;&gt;Llama 2 (기존 Meta/Invoke 방식)&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;어떤 모델들은 아예 복잡한 구분 없이 특정 기호([INST], &amp;lt;&amp;lt;SYS&amp;gt;&amp;gt;)를 섞은 긴 문장 하나로 보내달라고 요구&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwj93Pen9K2UAxUAAAAAHQAAAAAQuQE&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;prompt&quot;: &quot;[INST] 안녕? [/INST]&quot;,
  &quot;temperature&quot;: 0.5
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12&quot;&gt;Titan (Amazon 방식)&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;아마존 자체 모델은 또 입력 텍스트를 inputText라는 이름의 상자에 담으라고 요구&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwj93Pen9K2UAxUAAAAAHQAAAAAQugE&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;inputText&quot;: &quot;안녕?&quot;,
  &quot;textGenerationConfig&quot;: { &quot;maxTokenCount&quot;: 512 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3가지 방법 비교&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 126px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;구분&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;Session Key (&lt;/b&gt;&lt;span&gt;&lt;b&gt;세션&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;Anthropic API Key (&lt;/b&gt;&lt;span&gt;&lt;b&gt;직접&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;Amazon Bedrock (&lt;/b&gt;&lt;span&gt;&lt;b&gt;클라우드&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;핵심&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;개념&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;웹사이트&lt;span&gt; &lt;/span&gt;로그인&lt;span&gt; &lt;/span&gt;상태&lt;span&gt; &lt;/span&gt;공유&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;개발자&lt;span&gt; &lt;/span&gt;전용&lt;span&gt; '&lt;/span&gt;출입증&lt;span&gt;' &lt;/span&gt;발급&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span&gt;AWS &lt;/span&gt;인프라&lt;span&gt; &lt;/span&gt;내&lt;span&gt; &lt;/span&gt;모델&lt;span&gt; &lt;/span&gt;호출&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;비용&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;체계&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;월&lt;/b&gt;&lt;/span&gt;&lt;b&gt; $20 (Pro &lt;/b&gt;&lt;span&gt;&lt;b&gt;구독&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;종량제&lt;/b&gt;&lt;span&gt; (&lt;/span&gt;쓴&lt;span&gt; &lt;/span&gt;만큼&lt;span&gt; &lt;/span&gt;결제&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;종량제&lt;/b&gt;&lt;/span&gt; (AWS &lt;span&gt;통합&lt;/span&gt; &lt;span&gt;청구&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;설정&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;난이도&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;매우&lt;span&gt; &lt;/span&gt;쉬움&lt;span&gt; (&lt;/span&gt;로그인&lt;span&gt; &lt;/span&gt;방식&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;쉬움&lt;span&gt; (&lt;/span&gt;키&lt;span&gt; &lt;/span&gt;복사&lt;span&gt;/&lt;/span&gt;붙여넣기&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span&gt;복잡&lt;/span&gt; (IAM, &lt;span&gt;권한&lt;/span&gt;, &lt;span&gt;리전&lt;/span&gt; &lt;span&gt;설정&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;안정성&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;보통&lt;span&gt; (&lt;/span&gt;주기적&lt;span&gt; &lt;/span&gt;재로그인&lt;span&gt; &lt;/span&gt;필요&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;매우&lt;span&gt; &lt;/span&gt;높음&lt;span&gt; (&lt;/span&gt;키&lt;span&gt; &lt;/span&gt;만료&lt;span&gt; &lt;/span&gt;없음&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;매우&lt;span&gt; &lt;/span&gt;높음&lt;span&gt; (&lt;/span&gt;기업용&lt;span&gt; &lt;/span&gt;인프라&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;장점&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;추가&lt;span&gt; &lt;/span&gt;비용&lt;span&gt; &lt;/span&gt;없이&lt;span&gt; &lt;/span&gt;구독&lt;span&gt; &lt;/span&gt;혜택&lt;span&gt; &lt;/span&gt;활용&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;자동화&lt;span&gt;/&lt;/span&gt;봇&lt;span&gt; &lt;/span&gt;운영에&lt;span&gt; &lt;/span&gt;최적화&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;최고&lt;span&gt; &lt;/span&gt;수준의&lt;span&gt; &lt;/span&gt;보안&lt;span&gt;, AWS &lt;/span&gt;크레딧&lt;span&gt; &lt;/span&gt;활용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;단점&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span&gt;질문&lt;/span&gt; &lt;span&gt;횟수&lt;/span&gt; &lt;span&gt;제한&lt;/span&gt;(Quota) &lt;span&gt;공유&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;비용&lt;span&gt; &lt;/span&gt;관리&lt;span&gt; &lt;/span&gt;주의&lt;span&gt; (&lt;/span&gt;요금&lt;span&gt; &lt;/span&gt;폭탄&lt;span&gt; &lt;/span&gt;가능성&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;Claude Code &lt;span&gt;직접&lt;/span&gt; &lt;span&gt;연동&lt;/span&gt; &lt;span&gt;불가&lt;/span&gt; (MCP &lt;span&gt;필요&lt;/span&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://aws.amazon.com/ko/blogs/tech/bedrock-with-claude-code/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aws.amazon.com/ko/blogs/tech/bedrock-with-claude-code/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://wikidocs.net/329810&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://wikidocs.net/329810&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>amazon bedrock</category>
      <category>API Key</category>
      <category>claude code</category>
      <category>session key</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1850</guid>
      <comments>https://ios-development.tistory.com/1850#entry1850comment</comments>
      <pubDate>Wed, 13 May 2026 01:57:54 +0900</pubDate>
    </item>
    <item>
      <title>[AI] claude code - hook, btw 명령어 (클로드코드 훅, by the way)</title>
      <link>https://ios-development.tistory.com/1849</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;btw 명령어&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;btw&lt;/b&gt;는 &lt;b&gt;by the way&lt;/b&gt;의 줄임말 (&quot;그나저나&quot;)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 작업 흐름을 중단하거나 대화 기록(Context)을 오염시키지 않고, 샛길 질문(Side Question)을 빠르게 던질 수 있는 번들 스킬&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 게시판 웹 구현해달라고 할때, 도중에 클로드코드가 어떤 언어로 구현하는지 궁금한 경우, /btw로 물어볼 수 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bircJA/dJMcah5okCN/DijMObQEal6hpZf6ZKlTA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bircJA/dJMcah5okCN/DijMObQEal6hpZf6ZKlTA0/img.png&quot; data-alt=&quot;게시판 웹 구현해달라고 클로드코드한테 작업 시킴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bircJA/dJMcah5okCN/DijMObQEal6hpZf6ZKlTA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbircJA%2FdJMcah5okCN%2FDijMObQEal6hpZf6ZKlTA0%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;580&quot; height=&quot;132&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게시판 웹 구현해달라고 클로드코드한테 작업 시킴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAaDJ1/dJMcagyBDNv/MTIvdGBBX93MKPxYQTxscK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAaDJ1/dJMcagyBDNv/MTIvdGBBX93MKPxYQTxscK/img.png&quot; data-alt=&quot;게시판을 구현하고 있는 도중에 어떤 언어로 구현중인지 물어봄&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAaDJ1/dJMcagyBDNv/MTIvdGBBX93MKPxYQTxscK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAaDJ1%2FdJMcagyBDNv%2FMTIvdGBBX93MKPxYQTxscK%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;1392&quot; height=&quot;328&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;328&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게시판을 구현하고 있는 도중에 어떤 언어로 구현중인지 물어봄&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작업 도중에 토큰을 얼마나 쓸지도 물어볼 수 있음&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BPOkk/dJMcahj2xas/ENKR4ZFIbpKCvMTCknKQVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BPOkk/dJMcahj2xas/ENKR4ZFIbpKCvMTCknKQVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BPOkk/dJMcahj2xas/ENKR4ZFIbpKCvMTCknKQVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBPOkk%2FdJMcahj2xas%2FENKR4ZFIbpKCvMTCknKQVK%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;1726&quot; height=&quot;832&quot; data-origin-width=&quot;1726&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Hook 기능&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Hook은 Claude Code의 실행중에, 특정 이벤트가 발생하였을때 사용자가 정해 지정해놓은 Shell Command나, HTTP 요청 또는 프롬프트를 실행할 수 있는 기능&lt;/li&gt;
&lt;li&gt;주요 Hook들
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;Pre-execution Hooks:&lt;/b&gt; 클로드가 코드를 생성하거나 수정하기 직전에 실행 (예: 최신 API 문서 불러오기)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Post-execution Hooks:&lt;/b&gt; 클로드가 작업을 마친 직후 실행 (예: 린트(Lint) 체크, 빌드 테스트)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;Context Hooks:&lt;/b&gt; 특정 파일이나 디렉토리에 접근할 때 자동으로 맥락 정보를 제공하도록 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 프로젝트 루트에 있는 .claude/config.json 또는 클로드 전용 설정 파일 내에 훅을 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,0,0&quot;&gt;pre-apply:&lt;/b&gt; 클로드가 수정 사항을 파일에 적용하기 전에 실행할 명령어&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,1,0&quot;&gt;post-apply:&lt;/b&gt; 수정 사항이 적용된 후 정상 작동 여부를 확인하기 위한 명령어&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10,2,0&quot;&gt;on-error:&lt;/b&gt; 작업 중 오류가 발생했을 때 진단을 위해 실행할 명령어&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1777960266985&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;hooks&quot;: {
    &quot;pre-apply&quot;: &quot;npm run lint&quot;,
    &quot;post-apply&quot;: &quot;npm test&quot;,
    &quot;on-error&quot;: &quot;tail -n 20 error.log&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또 다른 활용 케에스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;-&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;설명&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;자동&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;테스트&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;클로드가&lt;span&gt; &lt;/span&gt;코드를&lt;span&gt; &lt;/span&gt;고친&lt;span&gt; &lt;/span&gt;후&lt;span&gt; &lt;/span&gt;자동으로&lt;span&gt; jest&lt;/span&gt;나&lt;span&gt; pytest&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;돌려&lt;span&gt; &lt;/span&gt;회귀&lt;span&gt; &lt;/span&gt;버그를&lt;span&gt; &lt;/span&gt;방지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;포맷팅&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;강제&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;수정한&lt;span&gt; &lt;/span&gt;코드가&lt;span&gt; &lt;/span&gt;프로젝트의&lt;span&gt; Prettier&lt;/span&gt;나&lt;span&gt; ESLint &lt;/span&gt;규칙을&lt;span&gt; &lt;/span&gt;준수하도록&lt;span&gt; &lt;/span&gt;자동&lt;span&gt; &lt;/span&gt;교정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;의존성&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;체크&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;package.json&lt;span&gt;이&lt;/span&gt; &lt;span&gt;변경되면&lt;/span&gt; &lt;span&gt;자동으로&lt;/span&gt; npm install&lt;span&gt;을&lt;/span&gt; &lt;span&gt;수행하도록&lt;/span&gt; &lt;span&gt;설정&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;문서&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;동기화&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;코드가&lt;span&gt; &lt;/span&gt;변경될&lt;span&gt; &lt;/span&gt;때마다&lt;span&gt; &lt;/span&gt;관련&lt;span&gt; &lt;/span&gt;사양서&lt;span&gt;(Swagger &lt;/span&gt;등&lt;span&gt;)&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;최신화하는&lt;span&gt; &lt;/span&gt;스크립트를&lt;span&gt; &lt;/span&gt;연결&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같은 Hook 타이밍이 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(참고: &lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://code.claude.com/docs/en/hooks&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/en/hooks&lt;/a&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;1244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJa0O/dJMcaaLXEco/nl0RxwvGA7KKbcXKhxNGok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJa0O/dJMcaaLXEco/nl0RxwvGA7KKbcXKhxNGok/img.png&quot; data-alt=&quot;https://code.claude.com/docs/en/hooks&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJa0O/dJMcaaLXEco/nl0RxwvGA7KKbcXKhxNGok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJa0O%2FdJMcaaLXEco%2Fnl0RxwvGA7KKbcXKhxNGok%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;532&quot; height=&quot;1244&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;1244&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://code.claude.com/docs/en/hooks&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 404px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;height: 10px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Event&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 10px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;When it fires (발생 시점)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SessionStart&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 시작되거나 재개될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UserPromptSubmit&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프롬프트를 제출했고, &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 처리하기 전&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PreToolUse&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 호출이 실행되기 전. (호출을 차단할 수 있음)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PermissionRequest&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Permission&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 대화 상자가 나타날 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PostToolUse&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 호출이 성공한 후&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 35px;&quot;&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PostToolUseFailure&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 35px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Tool&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 호출이 실패한 후&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Notification&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 알림을 보낼 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SubagentStart&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Subagent&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 생성될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SubagentStop&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Subagent&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 완료될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stop&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 응답을 마쳤을 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TeammateIdle&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Agent team&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 동료가 유휴 상태가 되기 직전&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TaskCompleted&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Task&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 완료로 표시될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;InstructionsLoaded&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;CLAUDE.md&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 또는 &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;.claude/rules/*.md&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 파일이 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 로드될 때. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 시작 시 및 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 중 파일이 지연 로드될 때 발생&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ConfigChange&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 중 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Configuration&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 파일이 변경될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WorktreeCreate&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;--worktree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 또는 &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;isolation: &quot;worktree&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 통해 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;worktree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 생성될 때. 기본 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 동작을 대체함&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;WorktreeRemove&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 종료 시 또는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Subagent&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 완료될 때 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;worktree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 제거될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PreCompact&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Context compaction&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 전&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SessionEnd&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Session&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 종료될 때&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/en/hooks&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/en/hooks&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://www.reddit.com/r/ClaudeCode/comments/1rqlry4/have_you_tried_the_new_btw_command/?tl=ko#:~:text=BTW%EB%8A%94%20subagent%EB%9E%91%20%EB%B0%98%EB%8C%80/%EC%97%AD%ED%95%A0%EC%9D%84%20%ED%95%98%EB%8A%94%20%EB%8B%A4%EB%A5%B8%20%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%9D%B8%EB%8D%B0%2C%20%ED%98%84%EC%9E%AC,%EB%A7%90%ED%95%9C%20%EA%B2%83%EC%B2%98%EB%9F%BC%2C%20%ED%9B%84%EC%86%8D%20%EC%A7%88%EB%AC%B8%20%EA%B0%99%EC%9D%80%20%EA%B1%B4%20%EC%97%86%EC%96%B4.&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.reddit.com/r/ClaudeCode/comments/1rqlry4/have_you_tried_the_new_btw_command/?tl=ko#:~:text=BTW%EB%8A%94%20subagent%EB%9E%91%20%EB%B0%98%EB%8C%80/%EC%97%AD%ED%95%A0%EC%9D%84%20%ED%95%98%EB%8A%94%20%EB%8B%A4%EB%A5%B8%20%EC%97%90%EC%9D%B4%EC%A0%84%ED%8A%B8%EC%9D%B8%EB%8D%B0%2C%20%ED%98%84%EC%9E%AC,%EB%A7%90%ED%95%9C%20%EA%B2%83%EC%B2%98%EB%9F%BC%2C%20%ED%9B%84%EC%86%8D%20%EC%A7%88%EB%AC%B8%20%EA%B0%99%EC%9D%80%20%EA%B1%B4%20%EC%97%86%EC%96%B4.&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>BTW</category>
      <category>claude code</category>
      <category>Hook</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <category>훅</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1849</guid>
      <comments>https://ios-development.tistory.com/1849#entry1849comment</comments>
      <pubDate>Wed, 6 May 2026 01:52:21 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 claude opus 4.7 내용 (claude-opus-4.7)</title>
      <link>https://ios-development.tistory.com/1848</link>
      <description>&lt;h4 data-path-to-node=&quot;4&quot; data-ke-size=&quot;size20&quot;&gt;1. 고해상도 이미지 지원 (Vision 성능 강화)&lt;/h4&gt;
&lt;p id=&quot;p-rc_a41691dd155c8f74-21&quot; data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그동안 Claude 모델의 이미지 해상도 제한 때문에 문서나 스크린샷 분석 시 아쉬운 점이 있었는데, 이번 4.7 버전에서 해상도가 크게 개선&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;&lt;span&gt;해상도 증가&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 기존 1568px(1.15MP) &amp;rarr; 최대 2576px(3.75MP)로 향상&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;&lt;span&gt;1:1 픽셀 매핑&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 모델의 좌표 시스템이 실제 픽셀과 1:1로 대응되어, 별도의 스케일 팩터 계산 없이도 정확한 좌표 추출이 가능해짐&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,0&quot;&gt;&lt;span&gt;활용&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 복잡한 UI 스크린샷 분석, 아티팩트 이해, 이미지 내 텍스트 및 사물 감지(Localization) 성능이 강화됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;2. 새로운 'xhigh' Effort Level 도입&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 low, medium, high, max 등의 단계가 있었는데, xhigh는 &lt;b data-index-in-node=&quot;49&quot; data-path-to-node=&quot;6&quot;&gt;high보다는 똑똑하고 max보다는 빠른&lt;/b&gt;&amp;nbsp;것&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;Low/Medium&lt;/b&gt;: 단순 요약, 번역, 가벼운 질의응답&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;High&lt;/b&gt;: 일반적인 코딩 지원, 복잡한 지시사항 이행&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;xhigh (신규)&lt;/b&gt;: &lt;b data-index-in-node=&quot;12&quot; data-path-to-node=&quot;7,2,0&quot;&gt;에이전트 기반 작업(Agentic workflows), 복합적인 버그 수정, 멀티 스텝 도구 사용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,3,0&quot;&gt;Max&lt;/b&gt;: 수학적 증명, 논문 수준의 고도의 추론 (시간이 가장 오래 걸림)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-path-to-node=&quot;9&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;9,2,0&quot; data-index-in-node=&quot;0&quot;&gt;참고&lt;/b&gt;: Claude Code에서는 이미 모든 플랜의 기본 설정이 xhigh로 상향&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size20&quot;&gt;3. 코딩 및 에이전트 성능 (State-of-the-Art)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;SW-bench 72.5%&lt;/b&gt;: 복잡하고 긴 작업에서도 집중력을 잃지 않고 수천 단계의 과정을 지속적으로 수행할 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;&lt;span&gt;자기 수정(Self-correction)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 코드를 짜다가 스스로 실수를 발견하고 수정하는 능력이 좋아져, 시니어 개발자가 난이도 높은 작업을 믿고 맡길 수 있는 수준(Confidently delegate)까지 올라옴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;&lt;span&gt;메모리 기능&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 로컬 파일 액세스 권한을 주었을 때, '메모리 파일'을 직접 생성하고 유지하며 정보를 저장하는 능력이 매우 뛰어남&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size20&quot;&gt;4. 가격 및 사용 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;14&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,0,0&quot;&gt;&lt;span&gt;가격&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: 기존 Opus 4.6과 동일&lt;/span&gt;&amp;nbsp;(Input $5/1M, Output $25/1M)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,1,0&quot;&gt;&lt;span&gt;플랫폼&lt;/span&gt;&lt;/b&gt;&lt;span&gt;: Claude Pro, Team, Enterprise 요금제 사용자는 바로 사용 가능하며, API와 Amazon Bedrock, Google Vertex AI에서도 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,2,0&quot;&gt;모델명&lt;/b&gt;: claude-opus-4-7&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://www.anthropic.com/news/claude-opus-4-7&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.anthropic.com/news/claude-opus-4-7&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude</category>
      <category>claude code</category>
      <category>claude-opus-4.7</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1848</guid>
      <comments>https://ios-development.tistory.com/1848#entry1848comment</comments>
      <pubDate>Wed, 29 Apr 2026 01:25:00 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 서브 에이전트 사용 방법 (SubAgent, agents, ClaudeCode, 병렬 처리)</title>
      <link>https://ios-development.tistory.com/1847</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;서브 에이전트란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 작업 유형을 처리하기위해 클로드코드에서 사용할 수 있는 AI 어시스턴트&lt;/li&gt;
&lt;li&gt;자주 쓰이는 툴이나, 프롬프트에 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 코드 리뷰, 성능 병목 지점 탐색, 단위 테스트 누락 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;서브 에이전트가 필요한 이유&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에이전트 없이 하나로만 AI를 사용한다면 context가 오염됨 (토큰 효율성 하락)&lt;/li&gt;
&lt;li&gt;비슷한 작업에 관한 재사용에 용이&lt;/li&gt;
&lt;li&gt;아래와 같이 병렬 작업이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zXqip/dJMcacQnHyv/IbLLbpd8pIMA4CKhqcZ1K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zXqip/dJMcacQnHyv/IbLLbpd8pIMA4CKhqcZ1K1/img.png&quot; data-alt=&quot;ex. 병렬작업 (https://tech.hyperithm.com/claude_code_guides_2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zXqip/dJMcacQnHyv/IbLLbpd8pIMA4CKhqcZ1K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzXqip%2FdJMcacQnHyv%2FIbLLbpd8pIMA4CKhqcZ1K1%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;930&quot; height=&quot;502&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ex. 병렬작업 (https://tech.hyperithm.com/claude_code_guides_2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;에이전트 만드는 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(vscode 사용하여 설명)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클로드코드 &amp;gt; &lt;b&gt;/agents&lt;/b&gt; 입력 후 엔터&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7ELvm/dJMcadhsgeU/7J7SAAnEBmsKUneVMZGUq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7ELvm/dJMcadhsgeU/7J7SAAnEBmsKUneVMZGUq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7ELvm/dJMcadhsgeU/7J7SAAnEBmsKUneVMZGUq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7ELvm%2FdJMcadhsgeU%2F7J7SAAnEBmsKUneVMZGUq1%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;1220&quot; height=&quot;380&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;terminal에서 사용할수 있기에 1번 선택된 상태로 엔터&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ci54H/dJMcafGl98e/CHSQBDLzEkOEXqtpVX1Pfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ci54H/dJMcafGl98e/CHSQBDLzEkOEXqtpVX1Pfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ci54H/dJMcafGl98e/CHSQBDLzEkOEXqtpVX1Pfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCi54H%2FdJMcafGl98e%2FCHSQBDLzEkOEXqtpVX1Pfk%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;1008&quot; height=&quot;516&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;516&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기다리면 자동으로 터미널 명령어 창에 claude /agents가 입력됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byzW1t/dJMcabRs5Lt/ju4koZstKA8euR9AxSxc3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byzW1t/dJMcabRs5Lt/ju4koZstKA8euR9AxSxc3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byzW1t/dJMcabRs5Lt/ju4koZstKA8euR9AxSxc3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyzW1t%2FdJMcabRs5Lt%2Fju4koZstKA8euR9AxSxc3K%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;812&quot; height=&quot;272&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;oh-my-claudecode를 사용하고 있어서 여러개가 나오는데, 새로 만들어볼 것이므로 선택되어 있는 &lt;b&gt;Create new agent&lt;/b&gt; 선택 후 엔터
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ios-development.tistory.com/1841&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;oh-my-claudecode는 이전 포스팅 글&lt;/a&gt; 참고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;1172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfuA6J/dJMcahRF3Xa/Wk2q1GhuVc37JhnLDpc9KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfuA6J/dJMcahRF3Xa/Wk2q1GhuVc37JhnLDpc9KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfuA6J/dJMcahRF3Xa/Wk2q1GhuVc37JhnLDpc9KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfuA6J%2FdJMcahRF3Xa%2FWk2q1GhuVc37JhnLDpc9KK%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;1092&quot; height=&quot;1172&quot; data-origin-width=&quot;1092&quot; data-origin-height=&quot;1172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치 위치 선택 (자율이지만 간단히 보기 위해 &lt;b&gt;1. Project&lt;/b&gt; 선택
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Project: 해당 프로젝트에만 반영&lt;/li&gt;
&lt;li&gt;Personal: 전역적으로 사용할 수 있도록 반영&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eD61o1/dJMcajomz3T/zxGyTBRBpsjPjMLoxjoAs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eD61o1/dJMcajomz3T/zxGyTBRBpsjPjMLoxjoAs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eD61o1/dJMcajomz3T/zxGyTBRBpsjPjMLoxjoAs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeD61o1%2FdJMcajomz3T%2FzxGyTBRBpsjPjMLoxjoAs1%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;850&quot; height=&quot;308&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1번 클로드코드로 생성 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPQ6u5/dJMcafsNsFf/vKHcfaECyaCI7ARlGZlz2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPQ6u5/dJMcafsNsFf/vKHcfaECyaCI7ARlGZlz2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPQ6u5/dJMcafsNsFf/vKHcfaECyaCI7ARlGZlz2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPQ6u5%2FdJMcafsNsFf%2FvKHcfaECyaCI7ARlGZlz2k%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;848&quot; height=&quot;338&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설명을 입력
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예시) &quot;코드를 분석하여 사람이 이해할 수 있도록 쉽게 자연어로 알려주는 분석 에이전트&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkXjal/dJMcabcQl6J/FCfBwzkaBjhY2TaUZiolUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkXjal/dJMcabcQl6J/FCfBwzkaBjhY2TaUZiolUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkXjal/dJMcabcQl6J/FCfBwzkaBjhY2TaUZiolUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkXjal%2FdJMcabcQl6J%2FFCfBwzkaBjhY2TaUZiolUk%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;1594&quot; height=&quot;426&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;툴 입력
&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 data-path-to-node=&quot;4,0,0&quot; data-index-in-node=&quot;0&quot;&gt;Read-only tools (읽기 전용 도구):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일 내용을 읽거나 데이터를 조회하는 기능. 시스템을 변경하지 않고 정보를 가져오기만 하므로 안전&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;4,1,0&quot; data-index-in-node=&quot;0&quot;&gt;Edit tools (편집 도구):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일을 수정, 삭제하거나 코드를 변경하는 기능. 에이전트가 직접 결과물을 만들어내야 할 때 필수&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;4,2,0&quot; data-index-in-node=&quot;0&quot;&gt;Execution tools (실행 도구):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;작성한 코드를 실제로 실행하거나 터미널 명령어를 입력하는 기능. 프로그램의 동작 여부를 확인할 때 사용&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;4,3,0&quot; data-index-in-node=&quot;0&quot;&gt;MCP tools (Model Context Protocol):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다양한 외부 서비스나 데이터베이스를 표준화된 방식으로 연결해주는 도구. (예: Google Drive, Slack, GitHub 연동 등)&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;4,4,0&quot; data-index-in-node=&quot;0&quot;&gt;Other tools (기타 도구):&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;위 분류에 속하지 않는 웹 검색이나 특정 API 호출 기능 등이 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(편의상 선택되어 있는 All tools을 적용하여 Continue에 커서를 대고 엔터)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TB4ir/dJMcagrHYQf/0UAamT2IFjQeURq8UfwgJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TB4ir/dJMcagrHYQf/0UAamT2IFjQeURq8UfwgJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TB4ir/dJMcagrHYQf/0UAamT2IFjQeURq8UfwgJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTB4ir%2FdJMcagrHYQf%2F0UAamT2IFjQeURq8UfwgJ1%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;1000&quot; height=&quot;554&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델 선택 (디폴트 Sonnet)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfpuZW/dJMcabYfRyy/knKZXRSZ6ROtTXsKQ1Njk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfpuZW/dJMcabYfRyy/knKZXRSZ6ROtTXsKQ1Njk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfpuZW/dJMcabYfRyy/knKZXRSZ6ROtTXsKQ1Njk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfpuZW%2FdJMcabYfRyy%2FknKZXRSZ6ROtTXsKQ1Njk1%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;1066&quot; height=&quot;400&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에이전트가 사용할 색 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KqK9b/dJMcaaLOvq7/YiBsZikbuyjm1xsMiheN3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KqK9b/dJMcaaLOvq7/YiBsZikbuyjm1xsMiheN3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KqK9b/dJMcaaLOvq7/YiBsZikbuyjm1xsMiheN3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKqK9b%2FdJMcaaLOvq7%2FYiBsZikbuyjm1xsMiheN3k%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;868&quot; height=&quot;620&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종 리뷰 -&amp;gt; Enter 누르면 완성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1946&quot; data-origin-height=&quot;1040&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XWX0x/dJMcahYshKR/kPzkK6NB56lKgj3P3lWSDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XWX0x/dJMcahYshKR/kPzkK6NB56lKgj3P3lWSDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XWX0x/dJMcahYshKR/kPzkK6NB56lKgj3P3lWSDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXWX0x%2FdJMcahYshKR%2FkPzkK6NB56lKgj3P3lWSDK%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;1946&quot; height=&quot;1040&quot; data-origin-width=&quot;1946&quot; data-origin-height=&quot;1040&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종 Agents목록에서 위에서 만든 &quot;code-explainer&quot; 생성된 것을 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;1312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k5wns/dJMcabcQmhg/XhGxT8Pqg4hYBJaKrwKtf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k5wns/dJMcabcQmhg/XhGxT8Pqg4hYBJaKrwKtf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k5wns/dJMcabcQmhg/XhGxT8Pqg4hYBJaKrwKtf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk5wns%2FdJMcabcQmhg%2FXhGxT8Pqg4hYBJaKrwKtf1%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;942&quot; height=&quot;1312&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;1312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;에이전트 사용 방법&lt;/h4&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Anq7g/dJMcabKKxkG/2BXDKwB51dIPn5SvBUfGJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Anq7g/dJMcabKKxkG/2BXDKwB51dIPn5SvBUfGJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Anq7g/dJMcabKKxkG/2BXDKwB51dIPn5SvBUfGJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAnq7g%2FdJMcabKKxkG%2F2BXDKwB51dIPn5SvBUfGJk%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;1032&quot; height=&quot;278&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔터를 누르면 적용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vwNSa/dJMb99TExNU/0TYXnUXkuQpvjKuvyMyYK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vwNSa/dJMb99TExNU/0TYXnUXkuQpvjKuvyMyYK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vwNSa/dJMb99TExNU/0TYXnUXkuQpvjKuvyMyYK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvwNSa%2FdJMb99TExNU%2F0TYXnUXkuQpvjKuvyMyYK0%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;988&quot; height=&quot;194&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병렬로 진행되게끔 하는 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 에이전트들을 부른 후 여러줄에 작성하면 사용이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1776860072050&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@.claude/agents/code-explainer.md: A부분 코드 분석해줘
@.claude/agents/create-flow-chart.md: B부분 플로우차트 그려줘&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://tech.hyperithm.com/claude_code_guides_2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tech.hyperithm.com/claude_code_guides_2&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>agents</category>
      <category>claudecode</category>
      <category>Subagent</category>
      <category>서브에이전트</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1847</guid>
      <comments>https://ios-development.tistory.com/1847#entry1847comment</comments>
      <pubDate>Wed, 22 Apr 2026 23:51:24 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 승인 요청 안물어보게 하는방법 (auto accept, bypass, vscode)</title>
      <link>https://ios-development.tistory.com/1846</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;vscode에서 bypass하게 하는 설정&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cmd + ,를 눌러서 `Claude Code: Allow Dangerously Skip Permissions` 검색
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 항목에 체크&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uiKEh/dJMcagLULfX/ykvCkuaWzvUo6VeFD6lVvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uiKEh/dJMcagLULfX/ykvCkuaWzvUo6VeFD6lVvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uiKEh/dJMcagLULfX/ykvCkuaWzvUo6VeFD6lVvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuiKEh%2FdJMcagLULfX%2FykvCkuaWzvUo6VeFD6lVvK%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;990&quot; height=&quot;396&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(체크완)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RgXbp/dJMcabRlfnp/OpemJGFYUKOwkGmAJqY4U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RgXbp/dJMcabRlfnp/OpemJGFYUKOwkGmAJqY4U1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RgXbp/dJMcabRlfnp/OpemJGFYUKOwkGmAJqY4U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRgXbp%2FdJMcabRlfnp%2FOpemJGFYUKOwkGmAJqY4U1%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;792&quot; height=&quot;198&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;체크하고나면 클로드코드 채팅창 오른쪽에 Bypass permissions라는 옵션이 생성됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 옵션을 누르고 다시 vscode를 실행하면 매번 권한을 물어보지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGIisj/dJMcabw15Qb/nV7ANDEutEHm4irdT3GO80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGIisj/dJMcabw15Qb/nV7ANDEutEHm4irdT3GO80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGIisj/dJMcabw15Qb/nV7ANDEutEHm4irdT3GO80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGIisj%2FdJMcabw15Qb%2FnV7ANDEutEHm4irdT3GO80%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;1198&quot; height=&quot;1608&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf) 터미널에서 bypass 설정하는 방법&lt;/p&gt;
&lt;pre id=&quot;code_1775981010319&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;claude --dangerously-skip-permissions&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;mcp관련 권한도 bypass 시키는 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 Bypass로 설정했음에도 불구하고 serena와 같은 mcp를 사용할때는 권한을 여전히 물어봄&lt;/li&gt;
&lt;li&gt;mcp에 관한 권한도 bypass 설정이 가능&lt;/li&gt;
&lt;li&gt;아래 설정 범위를 참고로하여 설정이 필요 (만약 글로벌, 로컬 중복된 내용이 있다면 로컬이 우선되어 적용됨)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;글로벌 설정:&lt;/b&gt; ~/.claude/settings.json (모든 프로젝트 적용)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;프로젝트 설정:&lt;/b&gt; &amp;lt;project&amp;gt;/.claude/settings.json (팀원과 공유됨)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;개인 로컬 설정:&lt;/b&gt; &amp;lt;project&amp;gt;/.claude/settings.local.json (Git 제외 권장)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;만약, 로컬 설정을 한다면 settings.local.json 파일을 열어서 `mcp__*` 라고 입력하여 모든 mcp에 관해 권한을 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1775980981452&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;permissions&quot;: {
    &quot;allow&quot;: [
      &quot;mcp__*&quot;
    ]
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>auto accept</category>
      <category>bypass</category>
      <category>claude code</category>
      <category>claudecode</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1846</guid>
      <comments>https://ios-development.tistory.com/1846#entry1846comment</comments>
      <pubDate>Wed, 15 Apr 2026 01:03:41 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 유용한 기능 (analyze, fix, explain, compact, call)</title>
      <link>https://ios-development.tistory.com/1845</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;유용한 기능&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 108px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;명령어&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;주요&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;목적&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;권장&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;사용&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;시점&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;/analyze&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;구조&lt;span&gt; &lt;/span&gt;파악&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;전략&lt;span&gt; &lt;/span&gt;수립&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;프로젝트&lt;span&gt; &lt;/span&gt;초기&lt;span&gt; &lt;/span&gt;진입&lt;span&gt;, &lt;/span&gt;대규모&lt;span&gt; &lt;/span&gt;변경&lt;span&gt; &lt;/span&gt;전&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;/fix&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;에러&lt;span&gt; &lt;/span&gt;해결&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;디버깅&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;빌드&lt;span&gt; &lt;/span&gt;에러&lt;span&gt; &lt;/span&gt;발생&lt;span&gt; &lt;/span&gt;시&lt;span&gt;, &lt;/span&gt;버그&lt;span&gt; &lt;/span&gt;리포트&lt;span&gt; &lt;/span&gt;접수&lt;span&gt; &lt;/span&gt;시&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;/explain&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;코드&lt;span&gt; &lt;/span&gt;이해&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;학습&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;모르는&lt;span&gt; &lt;/span&gt;로직&lt;span&gt; &lt;/span&gt;분석&lt;span&gt; &lt;/span&gt;시&lt;span&gt;, &lt;/span&gt;코드&lt;span&gt; &lt;/span&gt;리뷰&lt;span&gt; &lt;/span&gt;시&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;/compact&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;토큰&lt;span&gt; &lt;/span&gt;절약&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;성능&lt;span&gt; &lt;/span&gt;유지&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;대화가&lt;span&gt; &lt;/span&gt;너무&lt;span&gt; &lt;/span&gt;길어져&lt;span&gt; &lt;/span&gt;응답이&lt;span&gt; &lt;/span&gt;느려질&lt;span&gt; &lt;/span&gt;때&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;/call&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;전문&lt;span&gt; &lt;/span&gt;작업&lt;span&gt; &lt;/span&gt;위임&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;특정&lt;span&gt; &lt;/span&gt;규칙&lt;span&gt;(Lint &lt;/span&gt;등&lt;span&gt;) &lt;/span&gt;준수&lt;span&gt; &lt;/span&gt;여부&lt;span&gt; &lt;/span&gt;정밀&lt;span&gt; &lt;/span&gt;확인&lt;span&gt; &lt;/span&gt;시&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;/analyze (구조 파악 및 전략 수립)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트의 전체 아키텍처를 분석하여 개선 방향을 제시&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;Swift 상황&lt;/b&gt;: MVC에서 MVVM으로 전환하거나, 새로운 프레임워크 도입 전 사용&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;에이전트 액션&lt;/b&gt;: Target, Dependency, Folder Structure를 스캔&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;pre id=&quot;code_1775367288887&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 에이전트의 분석 결과 예시 (Summary)
/*
[Analysis Result]
- Project: SwiftUIMovieApp
- Architecture: Heavy View (MVC-like)
- Issues: 
  1. ContentListView.swift 내부에 네트워킹 로직이 포함됨 (150라인)
  2. 전역 싱글톤 NetworkManager 사용으로 테스트가 어려움
- Suggestion: ViewModel 도입 및 의존성 주입(DI) 패턴 적용 권장함
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;/fix (에러 해결 및 디버깅)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;빌드 에러나 런타임 크래시 로그를 바탕으로 코드를 즉시 수정함.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;Swift 상황&lt;/b&gt;: SwiftUI에서 @State 변경 시 발생하는 스레드 에러나 문법 오류 발생 시 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;pre id=&quot;code_1775367461202&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 수정 전 (에러 발생: Mutable property cannot be settled in a view)
struct ProfileView: View {
    var name: String = &quot;Gim&quot; // 빌드 에러 발생함
    
    var body: some View {
        Button(&quot;Change&quot;) { name = &quot;Jong-gwon&quot; }
    }
}

// /fix 실행 후 에이전트가 수정한 코드
struct ProfileView: View {
    @State private var name: String = &quot;Gim&quot; // @State 추가하여 해결함
    
    var body: some View {
        Button(&quot;Change&quot;) { name = &quot;Jong-gwon&quot; }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size20&quot;&gt;/explain (코드 이해 및 학습)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;난해한 Combine 연산자나 복잡한 동시성 제어 코드를 설명함.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;14&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,0,0&quot;&gt;Swift 상황&lt;/b&gt;: TaskGroup이나 AsyncSequence 등 복잡한 비동기 로직 분석 시 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1775367493567&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 분석 대상 코드
func fetchAllData() async throws -&amp;gt; [Data] {
    try await withThrowingTaskGroup(of: Data.self) { group in
        for url in urls {
            group.addTask { try await fetchData(from: url) }
        }
        return try await group.reduce(into: []) { $0.append($1) }
    }
}

/* 
[Agent Explanation]
이 코드는 'Structured Concurrency'를 사용하여 여러 URL에서 데이터를 병렬로 가져옴.
1. withThrowingTaskGroup: 에러 처리가 가능한 병렬 작업 그룹을 생성함.
2. addTask: 각 URL마다 개별 자식 태스크를 생성하여 비동기로 실행함.
3. reduce: 모든 작업이 완료될 때까지 기다렸다가 결과를 하나의 배열로 합쳐서 반환함.
*/&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size20&quot;&gt;/compact (토큰 절약 및 성능 유지)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;긴 코딩 세션 중 핵심 컨텍스트만 남기고 메모리를 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;19&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;19,0,0&quot;&gt;Swift 상황&lt;/b&gt;: 대규모 리팩토링 중 파일 10개를 넘나들며 대화가 길어졌을 때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775367555819&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// /compact 실행 시 내부 작동 방식
[System] 이전의 50개 대화 기록을 요약함.
[Current Context Summary]
- 현재 목표: 'NetworkModule'의 URLSession 설정을 에러 핸들링 로직과 함께 고도화 중임.
- 진행 상황: 'NetworkError.swift' 정의 완료, 'APIClient.swift' 수정 중임.
- 남은 작업: 단위 테스트(Unit Test) 작성 필요함.
(불필요한 이전 잡담 및 중복 코드 출력물 삭제 완료함)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;22&quot; data-ke-size=&quot;size20&quot;&gt;/call (전문 작업 위임)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;23&quot; data-ke-size=&quot;size16&quot;&gt;특정 규칙(Lint, Test 등)을 준수하는지 전문 에이전트에게 맡김&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;24&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;24,0,0&quot;&gt;Swift 상황&lt;/b&gt;: SwiftLint 규칙 준수 여부나 Unit Test 케이스 생성을 전담&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1775367599051&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# bash

# 터미널 호출 예시
/call swift_test_agent &quot;APIClient.swift 파일에 대한 성공/실패 테스트 케이스 5개 만들어줘&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1775367615452&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// swift

// /call로 호출된 서브에이전트가 생성한 코드
final class APIClientTests: XCTestCase {
    func test_fetchData_success() async throws {
        // Mock 데이터를 활용한 성공 케이스 로직 작성함
    }
    
    func test_fetchData_invalidURL_failure() async {
        // 잘못된 URL 입력 시 에러 반환 여부 검증함
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>ANALYZE</category>
      <category>Call</category>
      <category>claude code</category>
      <category>compact</category>
      <category>explain</category>
      <category>FIX</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1845</guid>
      <comments>https://ios-development.tistory.com/1845#entry1845comment</comments>
      <pubDate>Wed, 8 Apr 2026 01:41:03 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 sub agent 개념 (claude code, 서브 에이전트)</title>
      <link>https://ios-development.tistory.com/1844</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size23&quot;&gt;sub agent란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;메인 에이전트가 복잡한 작업을 수행할 때, 특정 역할에 특화된 '가상의 전문가'를 별도의 세션으로 띄워 작업을 위임하는 기능&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;메인 세션의 컨텍스트(대화 기록)가 너무 무거워지는 것을 방지하고, 특정 도구나 지침에만 집중하게 할 때 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;독립된 컨텍스트&lt;/b&gt;: 메인 대화와 분리된 깨끗한 창에서 작업하므로 토큰 소모가 효율적임&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;전문화된 지침&lt;/b&gt;: .agent 파일에 적힌 전용 시스템 프롬프트를 따름&lt;/li&gt;
&lt;li data-path-to-node=&quot;3&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,2,0&quot;&gt;도구 제한&lt;/b&gt;: 보안이나 정확도를 위해 특정 도구(예: 읽기 전용)만 사용하도록 제한 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 루트의 .claude/agents/ 디렉토리에 마크다운(.md) 파일을 만들어 에이전트를 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) &lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;파일명&lt;/b&gt;: .claude/agents/swift-reviewer.md&lt;/p&gt;
&lt;pre id=&quot;code_1774764649417&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: swift-reviewer
description: Swift 및 SwiftUI 코드의 품질을 검토하고 성능 최적화 방안을 제시하는 전문 리뷰어
tools: [ls, read_file, grep]
---

# 시스템 프롬프트
너는 10년 차 시니어 iOS 개발자임. 다음 원칙을 준수하여 코드를 리뷰함:
1. 메모리 누수 방지를 위해 `[weak self]` 사용 여부를 철저히 검사함
2. SwiftUI View 내 비즈니스 로직은 ViewModel로 분리할 것을 권고함
3. 가독성을 위해 한 함수는 30줄을 넘지 않도록 제안함&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;호출 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;12&quot;&gt;1) 자동 호출
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;12&quot;&gt;메인 에이전트에게 작업을 시키면, 에이전트가 판단하여 .agent 파일의 description과 일치하는 작업일 경우 서브에이전트를 생성함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-path-to-node=&quot;14&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-path-to-node=&quot;14,0&quot; data-ke-size=&quot;size16&quot;&gt;&quot;방금 수정한 LoginView.swift 파일을 &lt;b data-index-in-node=&quot;28&quot; data-path-to-node=&quot;14,0&quot;&gt;swift-reviewer&lt;/b&gt;로 검토해줘&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;18&quot;&gt;2) 에이전트 관리 (/agents 커맨드)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;18&quot;&gt;터미널에 /agents를 입력하면 현재 사용 가능한 내장/커스텀 에이전트 목록을 확인하고, UI를 통해 새 에이전트를 생성하거나 편집할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주의) Agent와 Skill 개념 구분&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;에이전트&lt;/b&gt;: &quot;로그인 페이지의 버그를 고쳐줘&quot;라는 요청을 받으면 '파일 검색 -&amp;gt; 코드 분석 -&amp;gt; 수정 -&amp;gt; 테스트'라는 &lt;b data-index-in-node=&quot;67&quot; data-path-to-node=&quot;8,0,0&quot;&gt;전체 과정을 주도&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;스킬&lt;/b&gt;: 에이전트가 &quot;파일을 읽어라&quot;라고 시키면 수행하는 read_file이나, &quot;테스트를 돌려라&quot;라고 할 때 쓰는 run_terminal_command 같은 &lt;b data-index-in-node=&quot;88&quot; data-path-to-node=&quot;8,1,0&quot;&gt;개별 함수&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;24&quot; data-ke-size=&quot;size20&quot;&gt;요약&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;25&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.skill은 &lt;b&gt;함수&lt;/b&gt;를 정의하고, .agent는 &lt;b&gt;지능의 성격과 규칙&lt;/b&gt;을 정의&lt;/li&gt;
&lt;li&gt;서브에이전트는 작업이 끝나면 결과를 메인 에이전트에게 보고하고 사라지는 &lt;b&gt;일회성 분신&lt;/b&gt;임&lt;/li&gt;
&lt;li&gt;팀 공통 규칙은 프로젝트 내 .claude/agents/에, 개인 선호 규칙은 ~/.claude/agents/에 저장하여 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/ko/sub-agents&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/sub-agents&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>Agent</category>
      <category>claude code</category>
      <category>ios</category>
      <category>sub agent</category>
      <category>Subagent</category>
      <category>SWIFT</category>
      <category>에이전트</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1844</guid>
      <comments>https://ios-development.tistory.com/1844#entry1844comment</comments>
      <pubDate>Wed, 1 Apr 2026 01:13:46 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 코드 리뷰 기능 (claude code, /code-review)</title>
      <link>https://ios-development.tistory.com/1843</link>
      <description>&lt;h3 data-path-to-node=&quot;1&quot; data-ke-size=&quot;size23&quot;&gt;/code-review 이란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-path-to-node=&quot;2&quot;&gt;여러 명의 AI 전문가가 협업하는 멀티 에이전트 오케스트레이션 방식으로 작동하여 코드의 품질과 보안, 논리적 결함을 심층적으로 검토
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;자율적 분석:&lt;/b&gt; 변경된 코드만 보는 것이 아니라, 전체 프로젝트 맥락을 이해하고 리뷰를 수행함&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;높은 신뢰도:&lt;/b&gt; 여러 에이전트가 교차 검증하여 오탐을 줄이고 실질적인 개선안을 제시함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size23&quot;&gt;주요 작동 메커니즘 (Agent Teams)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;리뷰 명령 시 각기 다른 전문성을 가진 에이전트들이 병렬로 투입됨&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,0,0&quot;&gt;규정 준수 에이전트:&lt;/b&gt; CLAUDE.md에 정의된 스타일 가이드 및 아키텍처 규칙 준수 여부 확인&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,1,0&quot;&gt;버그 탐지 에이전트:&lt;/b&gt; 논리적 오류, 엣지 케이스, 잠재적 메모리 누수 등 탐색&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,2,0&quot;&gt;컨텍스트 분석 에이전트:&lt;/b&gt; git blame 및 히스토리 분석을 통해 과거 수정 의도와의 충돌 여부 검토&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8,3,0&quot;&gt;최종 검증 에이전트:&lt;/b&gt; 발견된 이슈들의 우선순위를 정하고 신뢰도가 높은 항목만 필터링하여 보고&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size20&quot;&gt;주요 기능 및 활용 패턴&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;11&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;상세 설명&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;비고&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0,0&quot;&gt;CLAUDE.md 연동&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,1,1,0&quot;&gt;프로젝트 특유의 컨벤션을 학습하여 맞춤형 리뷰 수행&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,1,2,0&quot;&gt;&quot;Early return 사용&quot; 등 명시 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0,0&quot;&gt;인라인 피드백&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,2,1,0&quot;&gt;--comment 플래그 사용 시 GitHub PR에 직접 댓글 작성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,2,2,0&quot;&gt;CI/CD 연동 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,3,0,0&quot;&gt;심층 로직 검토&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,3,1,0&quot;&gt;단순 린터가 잡지 못하는 인증/인가 로직이나 성능 병목 파악&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;11,3,2,0&quot;&gt;대규모 PR에서 높은 효율&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;h4 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size20&quot;&gt;컨텍스트 비용 및 효율화 (Context Management)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;/code-review는 고성능 분석을 수행하므로 컨텍스트 소모와 비용 관리가 중요함&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;고비용 구조:&lt;/b&gt; 프로젝트 전체 정보를 로드하므로 대규모 코드베이스에서는 토큰 소모가 큼&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;최적화 팁:&lt;/b&gt; * &lt;b data-index-in-node=&quot;9&quot; data-path-to-node=&quot;15,1,0&quot;&gt;CLAUDE.md 정제:&lt;/b&gt; 리뷰 지침을 핵심 위주로 요약하여 매 요청 시 소모되는 컨텍스트를 줄임
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,1,0,0&quot;&gt;범위 지정:&lt;/b&gt; 전체 리뷰 대신 특정 디렉토리나 변경 파일 위주로 범위를 한정하여 실행&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,1,1,0&quot;&gt;Subagent 활용:&lt;/b&gt; 무거운 분석 작업은 별도 Subagent 루프로 분리하여 메인 세션의 메모리를 보호함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 폴더에 CLAUDE.md라는 파일 생성&lt;/li&gt;
&lt;li&gt;내용 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;pre id=&quot;code_1774448545552&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;SwiftUI View는 200줄 이하 유지함&quot;, &quot;강제 언래핑 금지함&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더욱 체계적으로는 아래처럼 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774448908275&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# CLAUDE.md

이 파일은 Claude Code가 프로젝트를 이해하고 코드 리뷰를 수행할 때 참고하는 지침 파일입니다.

## 프로젝트 개요

Swift로 작성된 간단한 유저 관리 모듈입니다.
Claude Code의 코드 리뷰 기능 데모를 위해 작성되었습니다.

## 코드 리뷰 기준

코드 리뷰 시 아래 항목을 반드시 점검하세요.

### 보안
- 비밀번호는 절대 평문으로 저장하거나 로그에 출력하지 않습니다.
- 하드코딩된 credentials(비밀번호, API 키 등)은 허용하지 않습니다.
- 민감한 정보는 Keychain 또는 환경변수를 통해 관리합니다.

### 안전성
- 배열 접근 시 반드시 범위(bounds) 체크를 수행합니다.
- 강제 언래핑(`!`)은 사용하지 않으며, `guard let` / `if let`을 사용합니다.
- 외부 입력값은 항상 검증합니다.

### Swift 코드 스타일
- 반복문보다 `filter`, `map`, `first(where:)` 등 고차 함수를 우선 사용합니다.
- `var`보다 `let`을 기본으로 사용합니다.
- 접근 제어자(`private`, `internal`)를 명시합니다.

### 일반 품질
- 함수는 단일 책임 원칙(SRP)을 따릅니다.
- 불필요한 `print` 디버그 로그는 제거합니다.
- 테스트 가능한 구조로 작성합니다.

## 리뷰 명령어

```
/review
```

위 명령어를 실행하면 Claude Code가 이 파일의 기준에 따라 코드를 리뷰합니다.&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;코드리뷰 대상 예제 코드 준비&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1774450036829&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// UserManager.swift

import Foundation

// 유저 모델
struct User {
    var id: Int
    var name: String
    var email: String
    var age: Int
    var password: String  // 평문 비밀번호 저장
}

class UserManager {
    var users: [User] = []
    var adminPassword = &quot;admin1234&quot;  // 하드코딩된 관리자 비밀번호

    // 유저 추가
    func addUser(id: Int, name: String, email: String, age: Int, password: String) {
        let user = User(id: id, name: name, email: email, age: age, password: password)
        users.append(user)
        print(&quot;Added user: \(name), password: \(password)&quot;)  // 비밀번호 로그 출력
    }

    // 이메일로 유저 검색
    func findUser(email: String) -&amp;gt; User? {
        for user in users {
            if user.email == email {
                return user
            }
        }
        return nil
    }

    // 나이로 필터링
    func getUsersByAge(minAge: Int, maxAge: Int) -&amp;gt; [User] {
        var result: [User] = []
        for user in users {
            if user.age &amp;gt;= minAge &amp;amp;&amp;amp; user.age &amp;lt;= maxAge {
                result.append(user)
            }
        }
        return result
    }

    // 유저 삭제 (인덱스로)
    func deleteUser(at index: Int) {
        users.remove(at: index)  // 범위 체크 없음, 크래시 위험
    }

    // 전체 유저 출력
    func printAllUsers() {
        for i in 0..&amp;lt;users.count {
            print(&quot;[\(i)] \(users[i].name) - \(users[i].email) - pw: \(users[i].password)&quot;)
        }
    }

    // 유저 수 반환
    func count() -&amp;gt; Int {
        return users.count
    }
}

// 사용 예시
let manager = UserManager()
manager.addUser(id: 1, name: &quot;Alice&quot;, email: &quot;alice@example.com&quot;, age: 28, password: &quot;secret123&quot;)
manager.addUser(id: 2, name: &quot;Bob&quot;, email: &quot;bob@example.com&quot;, age: 35, password: &quot;qwerty!&quot;)
manager.printAllUsers()

let found = manager.findUser(email: &quot;alice@example.com&quot;)
print(&quot;Found: \(found?.name ?? &quot;없음&quot;)&quot;)&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;클로드코드에 `/code-review` 입력하면 아래처럼 분석 완료&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;2084&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTvJd3/dJMcafzfss0/vvjLtitGsCCYDH7MHTsI6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTvJd3/dJMcafzfss0/vvjLtitGsCCYDH7MHTsI6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTvJd3/dJMcafzfss0/vvjLtitGsCCYDH7MHTsI6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTvJd3%2FdJMcafzfss0%2FvvjLtitGsCCYDH7MHTsI6K%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;1964&quot; height=&quot;2084&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;2084&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/ko/code-review&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/code-review&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>/code-review</category>
      <category>AI</category>
      <category>claude code</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1843</guid>
      <comments>https://ios-development.tistory.com/1843#entry1843comment</comments>
      <pubDate>Tue, 24 Mar 2026 22:25:29 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 개념 - 기본 개념(CLAUDE.md, skills, mcp, subagents, agent teams, hooks, plugins)</title>
      <link>https://ios-development.tistory.com/1842</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;에이전틱 루프 (The Agentic Loop)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 스스로 계획을 세우고 실행하는 에이전트 방식으로 작동하며 아래 3단계 과정이 반복&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;컨텍스트 탐색:&lt;/b&gt; 문제 해결에 필요한 파일 시스템을 조사하고 코드를 읽음&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;액션 실행:&lt;/b&gt; 코드 수정, 파일 생성, 터미널 명령(Shell) 실행 등을 직접 수행&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,2,0&quot;&gt;결과 검증:&lt;/b&gt; 변경 사항이 의도대로 반영되었는지 테스트를 돌려보고 결과를 분석&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 개념들&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;CLAUDE.md:&lt;/b&gt; 모든 세션에서 유지되는 프로젝트 컨텍스트로 코딩 컨벤션이나 규칙을 명시&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;Skills:&lt;/b&gt; 재사용 가능한 지식 및 워크플로우로 필요할 때 호출하거나 자동 로드&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,0&quot;&gt;Subagents:&lt;/b&gt; 독립된 루프를 실행하는 격리된 작업자로 무거운 작업을 수행하고 결과만 보고&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,3,0&quot;&gt;MCP:&lt;/b&gt; Slack, DB 등 외부 서비스와 연결하여 데이터를 주고받는 통로 역할&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,4,0&quot;&gt;Hooks:&lt;/b&gt; 파일 수정 등 특정 이벤트 발생 시 자동으로 실행되는 스크립트&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상황별 예제&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;9&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;주요 용도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0,0&quot;&gt;CLAUDE.md&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,1,1,0&quot;&gt;상시 적용 규칙&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,1,2,0&quot;&gt;&quot;pnpm 사용&quot;, &quot;커밋 전 빌드 필수&quot;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0,0&quot;&gt;Skill&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,2,1,0&quot;&gt;특정 작업 지식&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,2,2,0&quot;&gt;배포 체크리스트(/deploy), API 가이드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,3,0,0&quot;&gt;Subagent&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,3,1,0&quot;&gt;맥락 격리/병렬 처리&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,3,2,0&quot;&gt;수백 개의 파일 분석, 보안 취약점 조사&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,4,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,4,0,0&quot;&gt;Hook&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,4,1,0&quot;&gt;자동화 프로세스&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;9,4,2,0&quot;&gt;코드 수정 후 자동 Lint/Format 실행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비용&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 확장은 모델의 기억 공간을 소모하므로 효율적인 관리가 필요&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;고비용:&lt;/b&gt; CLAUDE.md와 MCP는 매 요청마다 많은 정보를 로드하므로 핵심 위주로 구성&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;저비용:&lt;/b&gt; Skills는 평소엔 요약본만 들고 있다가 필요할 때만 전체 내용을 로드&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,2,0&quot;&gt;효율화:&lt;/b&gt; 무거운 작업은 Subagent로 넘겨 메인 세션의 컨텍스트 소모를 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, &lt;/b&gt;CLAUDE.md로 기본 틀을 잡고 반복 작업은 Skill로 정의하며 외부 연결은 MCP를 활용해 자율적인 개발 환경을 구축하는 것이 핵심&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;1&quot; data-ke-size=&quot;size20&quot;&gt;주요 기능 조합 패턴 (Combination Patterns)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;2&quot; data-ke-size=&quot;size16&quot;&gt;각 확장 기능은 고유의 역할이 있으며 이를 조합해 시너지가 가능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;Skill + MCP:&lt;/b&gt; MCP로 외부를 연결하고 Skill로 사용법을 가이드함 (예: DB 연결 + 쿼리 패턴 가이드)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;Skill + Subagent:&lt;/b&gt; 하나의 Skill이 여러 Subagent를 생성해 병렬 작업을 수행함 (예: 보안/성능/스타일 동시 검토)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,2,0&quot;&gt;CLAUDE.md + Skills:&lt;/b&gt; 상시 규칙은 CLAUDE.md에, 방대한 참조 문서는 Skill에 넣어 필요할 때만 로드함&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,3,0&quot;&gt;Hook + MCP:&lt;/b&gt; 이벤트 발생 시 외부로 알림을 보냄 (예: 코드 수정 후 Slack 알림 발송)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;4&quot; data-ke-size=&quot;size20&quot;&gt;컨텍스트 비용 및 로드 전략 (Context Costs)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;확장 기능을 많이 추가할수록 모델의 기억 공간(Context)을 소모하며 효율적인 관리가 필수&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;6&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;로드 시점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;로드 내용&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;컨텍스트 비용&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,1,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0,0&quot;&gt;CLAUDE.md&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,1,1,0&quot;&gt;세션 시작 시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,1,2,0&quot;&gt;파일 전체 내용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,1,3,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,3,0&quot;&gt;매우 높음&lt;/b&gt; (매 요청 포함)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,2,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,0,0&quot;&gt;Skills&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,2,1,0&quot;&gt;시작 시 + 사용 시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,2,2,0&quot;&gt;요약 설명(시작), 전체(사용)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,2,3,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,3,0&quot;&gt;낮음&lt;/b&gt; (설명만 상주)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,3,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,3,0,0&quot;&gt;MCP&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,3,1,0&quot;&gt;세션 시작 시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,3,2,0&quot;&gt;도구 정의 및 스키마&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,3,3,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,3,3,0&quot;&gt;높음&lt;/b&gt; (매 요청 포함)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,4,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,4,0,0&quot;&gt;Subagents&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,4,1,0&quot;&gt;생성 시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,4,2,0&quot;&gt;지정된 스킬 포함 새 컨텍스트&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,4,3,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,4,3,0&quot;&gt;격리됨&lt;/b&gt; (메인 세션 무관)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,5,0,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,5,0,0&quot;&gt;Hooks&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,5,1,0&quot;&gt;트리거 시&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,5,2,0&quot;&gt;없음 (외부 실행)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;6,5,3,0&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,5,3,0&quot;&gt;0&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;효율적인 운영 팁&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;CLAUDE.md 최적화:&lt;/b&gt; 500줄 이내로 유지하고 상세 내용은 Skill로 분리함&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;Skill 호출 제어:&lt;/b&gt; 직접 호출할 스킬은 disable-model-invocation: true 설정을 통해 평상시 비용을 제로로 유지함&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;작업 격리:&lt;/b&gt; 많은 파일을 읽어야 하는 조사는 Subagent를 활용해 메인 세션의 메모리를 아낌&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;요약하자면,&lt;/b&gt; 모든 기능을 무분별하게 활성화하기보다 CLAUDE.md는 최소화하고 무거운 작업은 Skill과 Subagent로 분산하여 모델의 추론 효율을 유지하는 것이 핵심&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;* 참고: &lt;a href=&quot;https://code.claude.com/docs/en/features-overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/en/features-overview&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>claude</category>
      <category>claude code</category>
      <category>CLAUDE.md</category>
      <category>ios</category>
      <category>MCP</category>
      <category>Skills</category>
      <category>subagents</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1842</guid>
      <comments>https://ios-development.tistory.com/1842#entry1842comment</comments>
      <pubDate>Wed, 18 Mar 2026 01:22:53 +0900</pubDate>
    </item>
    <item>
      <title>[AI] Oh My Claude Code (omc) 이해하기</title>
      <link>https://ios-development.tistory.com/1841</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;oh my claude code의 컨셉&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;설계/실행/QA/검증&quot;을 적절한 모델로 알아서 잘 하게끔 AI한테 쉽게 명령어하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1772947175116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Multi-agent orchestration for Claude Code. Zero learning curve.&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;여러가지의 agent들을 지휘하며, 하나의 곡을 완성한다는 의미로 &lt;b&gt;orchestration&lt;/b&gt;이라고 함&lt;/li&gt;
&lt;li&gt;oh my claude code의 역할
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;oh my claude code 없이 내가 새롭게 구현하려는 기능이 있을때, claude code에게 &quot;기능을 구현해줘&quot; 한 후 &quot;테스트 해줘&quot;라고 두 번 말해야 함&lt;/li&gt;
&lt;li&gt;oh my claude code를 사용한다면, &lt;b&gt;ralph&lt;/b&gt;모드를 사용하여 새로운 기능을 구현해주고 동시에 테스트까지 해주고, 복잡한 로직은 opus, 쉬운 작업은 haiku를 알아서 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1772947577166&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; ╔══════════════════════════════════════════════╗
 ║                                              ║
 ║       OH MY CLAUDE CODE                   ║
 ║                                              ║
 ║   ┌─────────┐                                ║
 ║   │CONDUCTOR│  ──&amp;rarr;    architect (Opus)     ║
 ║   │ (Claude) │  ──&amp;rarr;    executor (Sonnet)   ║
 ║   │         │  ──&amp;rarr;    designer (Sonnet)    ║
 ║   │        │  ──&amp;rarr;    debugger (Sonnet)   ║
 ║   └─────────┘  ──&amp;rarr;    explore (Haiku)     ║
 ║                                              ║
 ║   &quot;1명의 AI &amp;rarr; 28인 전문가 팀으로&quot;            ║
 ║                                              ║
 ╚══════════════════════════════════════════════╝&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;agents들의 메모리 공유 방식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;oh my claude code를 사용하면 여러 agent들이 동시에 동작하는데, 내부적으로 효율적인 메모리 공유의 전략이 있음&lt;/li&gt;
&lt;li&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;공유 파일 (CLAUDE.md / MEMORY.md): 프로젝트의 전역 규칙(코딩 컨벤션, 아키텍처)을 모든 에이전트가 공유함&lt;/li&gt;
&lt;li&gt;Auto-Memory:&amp;nbsp;에이전트가&amp;nbsp;작업을&amp;nbsp;수행하며&amp;nbsp;새로&amp;nbsp;알게&amp;nbsp;된&amp;nbsp;사실(예:&amp;nbsp;&quot;이&amp;nbsp;프로젝트는&amp;nbsp;커스텀&amp;nbsp;에러&amp;nbsp;핸들러를&amp;nbsp;씀&quot;)을&amp;nbsp;~/.claude/projects/.../memory/에&amp;nbsp;기록하고,&amp;nbsp;다른&amp;nbsp;에이전트가&amp;nbsp;이를&amp;nbsp;참조&lt;/li&gt;
&lt;li&gt;컨텍스트 격리: 하위 에이전트가 수천 줄의 로그나 파일을 읽어도, 그 상세 내용은 메인 에이전트의 대화창을 오염시키지 않고 에이전트는 요약된 결과물만 메인에게 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;병렬 처리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;oh my claude code에서 &lt;b&gt;/ultrawork&lt;/b&gt; 하여 사용&lt;/li&gt;
&lt;li&gt;아래와 같은 3가지 방법을 사용&lt;/li&gt;
&lt;li&gt;1. 분산 워커 프로세스 (Worker Processes)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 에이전트가 작업을 쪼개면, 각 작업은 별도의 &lt;b data-index-in-node=&quot;28&quot; data-path-to-node=&quot;9,0,0&quot;&gt;자식 프로세스&lt;/b&gt;에서 독립적으로 돌아감&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;이점:&lt;/b&gt; 한 에이전트가 무거운 연산을 해도 메인 인터페이스가 멈추지 않고, 각 프로세스는 할당된 메모리 범위 내에서만 자원을 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2. 지능형 모델 라우팅
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 작업에 비싼 모델(Claude 3.5 Sonnet 등)을 쓰지 않음&lt;/li&gt;
&lt;li&gt;단순 파일 탐색은 가벼운 모델에게 맡기고, 복잡한 추론만 메인 모델이 처리하여 메모리 점유율과 비용을 동시에 최적화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;3. 토큰 절약 모드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병렬 작업 시 중복되는 컨텍스트를 제거하고 여러 에이전트가 동일한 라이브러리 문서를 읽어야 한다면, 이를 캐싱하거나 공통 참조 포인트로 연결해 토큰 소비를 &lt;b data-index-in-node=&quot;87&quot; data-path-to-node=&quot;13,0,0&quot;&gt;30~50%&lt;/b&gt; 줄임&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://memoryhub.tistory.com/entry/%F0%9F%8E%BC-Oh-My-Claude-Code-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84%EA%B9%8C%EC%A7%80-%EC%99%84%EC%A0%84-%ED%95%B4%EB%B6%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://memoryhub.tistory.com/entry/%F0%9F%8E%BC-Oh-My-Claude-Code-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84%EA%B9%8C%EC%A7%80-%EC%99%84%EC%A0%84-%ED%95%B4%EB%B6%80&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Yeachan-Heo/oh-my-claudecode&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;- https://github.com/Yeachan-Heo/oh-my-claudecode&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>claude clode</category>
      <category>ios</category>
      <category>oh my claude code</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <category>클로드코드 아키텍쳐</category>
      <category>클로드코드 컨셉</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1841</guid>
      <comments>https://ios-development.tistory.com/1841#entry1841comment</comments>
      <pubDate>Wed, 11 Mar 2026 01:41:17 +0900</pubDate>
    </item>
    <item>
      <title>[AI] oh-my-claude code 개념 (클로드코드, 클로드코드 플러그인, omc, oh my claude code)</title>
      <link>https://ios-development.tistory.com/1840</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;oh-my-claude code란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;= omc(oh my claude code)라고 지칭&lt;/li&gt;
&lt;li&gt;claude code를 위한 멀티 에이전트 오케스트레이션 플러그인&lt;/li&gt;
&lt;li&gt;여러&amp;nbsp;명의&amp;nbsp;전문&amp;nbsp;AI&amp;nbsp;에이전트가&amp;nbsp;협업하여&amp;nbsp;복잡한&amp;nbsp;코딩&amp;nbsp;작업을&amp;nbsp;수행하도록&amp;nbsp;설계&lt;/li&gt;
&lt;li&gt;claude code의 market이라는 오픈소스 마켓에 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;핵심 기능&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;32개의 전문 에이전트:&lt;/b&gt; 아키텍처 설계(Architect), 코드 실행(Executor), 디자인(Designer), 테스트(Tester), 보안 리뷰(Security) 등 역할이 세분화된 에이전트들이 협업&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;자동 위임:&lt;/b&gt; 사용자가 명령을 내리면 시스템이 작업의 성격에 맞는 최적의 에이전트를 자동으로 선택하여 배정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vscode에서 클로드코드를 쓰고 있다면 클로드코드 챗에서 manage plugins 진입
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;/plugin&quot; 입력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU6Il7/dJMcab4ndI9/9EVPdy7m0lb2yLc8J4Us90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU6Il7/dJMcab4ndI9/9EVPdy7m0lb2yLc8J4Us90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU6Il7/dJMcab4ndI9/9EVPdy7m0lb2yLc8J4Us90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU6Il7%2FdJMcab4ndI9%2F9EVPdy7m0lb2yLc8J4Us90%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;662&quot; height=&quot;388&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;manage plugins가 뜨면 &lt;b&gt;Marketplaces&lt;/b&gt; 탭 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlWzyq/dJMcafeGhtM/yiNDypLKZypMuOVlEKXx91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlWzyq/dJMcafeGhtM/yiNDypLKZypMuOVlEKXx91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlWzyq/dJMcafeGhtM/yiNDypLKZypMuOVlEKXx91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlWzyq%2FdJMcafeGhtM%2FyiNDypLKZypMuOVlEKXx91%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;644&quot; height=&quot;566&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;omc 레포 주소 입력 후 add 버튼 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1772450661369&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;https://github.com/Yeachan-Heo/oh-my-claudecode&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;1274&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcdGxG/dJMb996zrCc/xw65uukokPhjHF5kCaFml1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcdGxG/dJMb996zrCc/xw65uukokPhjHF5kCaFml1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcdGxG/dJMb996zrCc/xw65uukokPhjHF5kCaFml1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcdGxG%2FdJMb996zrCc%2Fxw65uukokPhjHF5kCaFml1%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;1274&quot; height=&quot;510&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의) 만약 xcode 관련 오류가 나오면 아래 명령어 실행&lt;/p&gt;
&lt;pre id=&quot;code_1772451021729&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo xcodebuild -license accept&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;다시 Plugins 탭을 누르면 생성된 것을 확인 -&amp;gt; Install 버튼 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CmSR3/dJMcagED27n/c9z3b1kxm9lRDK1JF6BlZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CmSR3/dJMcagED27n/c9z3b1kxm9lRDK1JF6BlZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CmSR3/dJMcagED27n/c9z3b1kxm9lRDK1JF6BlZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCmSR3%2FdJMcagED27n%2Fc9z3b1kxm9lRDK1JF6BlZK%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;1258&quot; height=&quot;696&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치와 활성화가 완료된것을 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cz9CYx/dJMcacI0Dnb/toRwtRMN3QWMSK7MOb1W1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cz9CYx/dJMcacI0Dnb/toRwtRMN3QWMSK7MOb1W1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cz9CYx/dJMcacI0Dnb/toRwtRMN3QWMSK7MOb1W1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcz9CYx%2FdJMcacI0Dnb%2FtoRwtRMN3QWMSK7MOb1W1k%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;1258&quot; height=&quot;684&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size26&quot;&gt;주요 명령어&lt;/h2&gt;
&lt;h3 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size23&quot;&gt;1. 자율 실행 모드 (Autonomous)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;/autopilot&lt;/b&gt;: 아이디어 제시부터 최종 코드 완성까지 전 과정 자율 수행
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,1,0,0&quot;&gt;예시: /autopilot 로그인 페이지에 소셜 로그인(Google, Apple) 기능을 추가해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;/ralph&lt;/b&gt;: 아키텍트 검증 기반의 반복 최적화 루프 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,1,0,0&quot;&gt;예시: /ralph API 응답 시간을 50% 개선해줘. 프로파일링부터 최적화까지 진행해&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;/ultrawork&lt;/b&gt;: 대규모 다중 작업을 병렬로 고속 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,1,0,0&quot;&gt;예시: /ultrawork 모든 API 엔드포인트에 입력 검증 추가, 에러 핸들링 통일, 로깅 추가&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size23&quot;&gt;2. 팀 및 병렬 실행 (Collaboration)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;/team&lt;/b&gt;: 역할이 분담된 여러 에이전트 간의 협업 수행
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,1,0,0&quot;&gt;예시: /team 프론트엔드 리팩토링과 백엔드 API 마이그레이션을 동시에 진행해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;/omc-teams&lt;/b&gt;: Claude, Codex, Gemini 등 이기종 모델을 tmux에서 동시 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,1,0,0&quot;&gt;예시: /omc-teams claude로 테스트 작성, codex로 리팩토링, gemini로 문서 생성해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;/ccg&lt;/b&gt;: 3개 모델(Claude, Codex, Gemini)을 동시에 활용한 오케스트레이션
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,1,0,0&quot;&gt;예시: /ccg 사용자 대시보드 페이지를 만들어줘. 백엔드 API와 프론트 UI 모두 필요해&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size23&quot;&gt;3. 계획 및 분석 (Planning)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;/plan&lt;/b&gt;: 복잡한 아키텍처 전환 등 전략적 실행 계획 수립
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,1,0,0&quot;&gt;예시: /plan 모놀리식 아키텍처를 마이크로서비스로 전환하려면 어떻게 해야 할까?&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;/analyze&lt;/b&gt;: 메모리 누수 등 심층적인 코드 베이스 조사
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,1,0,0&quot;&gt;예시: /analyze 현재 프로젝트의 메모리 누수 원인을 찾아줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;/ralph-init&lt;/b&gt;: 요구사항 명세서(PRD) 및 문서 초기화
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,1,0,0&quot;&gt;예시: /ralph-init 실시간 채팅 기능에 대한 요구사항 문서를 만들어줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size23&quot;&gt;4. 코드 품질 및 검증 (Quality &amp;amp; QA)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,0,0&quot;&gt;/code-review&lt;/b&gt;: 코드 품질 및 보안 취약점 종합 점검
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,0,1,0,0&quot;&gt;예시: /code-review 최근 커밋에서 변경된 파일들을 리뷰해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,0&quot;&gt;/security-review&lt;/b&gt;: 보안 취약점 집중 리뷰
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,1,0,0&quot;&gt;예시: /security-review 인증/인가 관련 코드에 보안 취약점이 있는지 확인해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,2,0&quot;&gt;/simplify&lt;/b&gt;: 복잡한 코드를 클린 코드로 리팩토링
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,2,1,0,0&quot;&gt;예시: /simplify 방금 작성한 코드를 더 깔끔하게 정리해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,3,0&quot;&gt;/build-fix&lt;/b&gt;: 빌드 에러 및 TypeScript 타입 오류 자동 수정
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,3,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,3,1,0,0&quot;&gt;예시: /build-fix TypeScript 컴파일 에러 전부 고쳐줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,4,0&quot;&gt;/tdd&lt;/b&gt;: 테스트 주도 개발 기반 기능 구현
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,4,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,4,1,0,0&quot;&gt;예시: /tdd 장바구니 기능을 TDD 방식으로 구현해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,5,0&quot;&gt;/ultraqa&lt;/b&gt;: 테스트 &amp;rarr; 검증 &amp;rarr; 수정을 성공할 때까지 무한 반복
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13,5,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,5,1,0,0&quot;&gt;예시: /ultraqa 전체 테스트 스위트를 돌리고, 실패하는 것들을 모두 수정해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;14&quot; data-ke-size=&quot;size23&quot;&gt;5. 유틸리티 및 설정 (Utility)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,0&quot;&gt;/note&lt;/b&gt;: 세션이 종료되어도 유지되는 중요 정보 메모
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,0,1,0,0&quot;&gt;예시: /note DB 마이그레이션 시 반드시 백업 먼저 실행할 것&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,0&quot;&gt;/deepinit&lt;/b&gt;: 프로젝트 구조 분석 및 가이드 문서(AGENTS.md) 자동 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,1,1,0,0&quot;&gt;예시: /deepinit 이 프로젝트의 구조를 분석하고 AGENTS.md를 생성해줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,0&quot;&gt;/skill&lt;/b&gt;: 에이전트의 로컬 스킬 관리 (list, add, remove)
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,2,1,0,0&quot;&gt;예시: /skill add # 새 스킬 추가&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,3,0&quot;&gt;/external-context&lt;/b&gt;: 외부 공식 문서 등 외부 컨텍스트 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,3,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,3,1,0,0&quot;&gt;예시: /external-context SwiftUI의 최신 NavigationStack 사용법을 찾아줘&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,4,0&quot;&gt;/omc-setup / /omc-doctor&lt;/b&gt;: 환경 설정 및 설치 문제 진단
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15,4,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i data-index-in-node=&quot;0&quot; data-path-to-node=&quot;15,4,1,0,0&quot;&gt;예시: /omc-setup # 최초 설치 마법사 시작&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-path-to-node=&quot;16&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size23&quot;&gt;✅ 권장 워크플로우&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;18&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,0,0&quot;&gt;/omc-setup&lt;/b&gt;: 초기 환경 설정 수행&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,1,0&quot;&gt;/plan&lt;/b&gt;: 구현 전 구체적인 작업 계획 수립&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,2,0&quot;&gt;/autopilot&lt;/b&gt;: 세워진 계획에 따라 자율 구현 시작&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,3,0&quot;&gt;/code-review&lt;/b&gt;: 최종 결과물의 품질 및 에러 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://github.com/Yeachan-Heo/oh-my-claudecode&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/Yeachan-Heo/oh-my-claudecode&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>ios</category>
      <category>oh my claude code</category>
      <category>oh-my-claude code</category>
      <category>OMC</category>
      <category>클로드코드</category>
      <category>클로드코드 플러그인</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1840</guid>
      <comments>https://ios-development.tistory.com/1840#entry1840comment</comments>
      <pubDate>Wed, 4 Mar 2026 01:39:15 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 오픈코드에서 클로드코드 사용 제한 이슈 (Claude code, opencode, anthropic, authorized)</title>
      <link>https://ios-development.tistory.com/1839</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드코드 사용시 에러&lt;/h4&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;클로드코드를 opencode와 같이 다른 곳에서 사용 시 중지시키는 사례가 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;i&gt;이&amp;nbsp;자격&amp;nbsp;증명은&amp;nbsp;Claude&amp;nbsp;Code에서만&amp;nbsp;사용하도록&amp;nbsp;승인되었으며&amp;nbsp;다른&amp;nbsp;API&amp;nbsp;요청에는&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;없습니다.&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;(This credential is only authorized for use with Claude Code and cannot&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;be used for other API requests.)&lt;/i&gt;&lt;i&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCK1Ht/dJMcahjaGx5/p6wkNLKffr3X0HDACt5490/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCK1Ht/dJMcahjaGx5/p6wkNLKffr3X0HDACt5490/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCK1Ht/dJMcahjaGx5/p6wkNLKffr3X0HDACt5490/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCK1Ht%2FdJMcahjaGx5%2Fp6wkNLKffr3X0HDACt5490%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;1612&quot; height=&quot;756&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오픈코드 레포에 issue로 문의를 해도 github action으로 아래 케이스가 있는지 확인하라는 문의가 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;740&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzOCkP/dJMcajnFcFD/KxQ4mfiN4aF0LvpKnVEkBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzOCkP/dJMcajnFcFD/KxQ4mfiN4aF0LvpKnVEkBk/img.png&quot; data-alt=&quot;https://github.com/anomalyco/opencode/issues/10956&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzOCkP/dJMcajnFcFD/KxQ4mfiN4aF0LvpKnVEkBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzOCkP%2FdJMcajnFcFD%2FKxQ4mfiN4aF0LvpKnVEkBk%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;1894&quot; height=&quot;740&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;740&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/anomalyco/opencode/issues/10956&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;오픈코드에서 클로드코드 사용을 금지한 코드&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anomalyco/opencode/commit/973715f3da1839ef2eba62d4140fe7441d539411#diff-23c1b48647ee5935d7825f0f38195a8e018b726e1e331bcc0fcc8f8ce85e4c71L335&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;오픈코드 레포&lt;/a&gt;를 가보면 클로드코드 관련 설정을 지운 커밋이 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pjkid/dJMcafFC8BA/5WAGv2c7HqP1iWbvdbrRu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pjkid/dJMcafFC8BA/5WAGv2c7HqP1iWbvdbrRu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pjkid/dJMcafFC8BA/5WAGv2c7HqP1iWbvdbrRu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpjkid%2FdJMcafFC8BA%2F5WAGv2c7HqP1iWbvdbrRu0%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;1294&quot; height=&quot;572&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앤트로픽 관련 설명 파일에 금지한다는 내용도 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2054&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7NuJ7/dJMcaiI45qV/OZv5qLvwidCpKFPbW8HHTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7NuJ7/dJMcaiI45qV/OZv5qLvwidCpKFPbW8HHTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7NuJ7/dJMcaiI45qV/OZv5qLvwidCpKFPbW8HHTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7NuJ7%2FdJMcaiI45qV%2FOZv5qLvwidCpKFPbW8HHTk%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;2054&quot; height=&quot;254&quot; data-origin-width=&quot;2054&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;thdxr이라는 사람의 커밋이며, 2026년 2월 20일에 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdFeSO/dJMcaa5odjh/MLbKeRE7cREeDiggKeozk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdFeSO/dJMcaa5odjh/MLbKeRE7cREeDiggKeozk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdFeSO/dJMcaa5odjh/MLbKeRE7cREeDiggKeozk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdFeSO%2FdJMcaa5odjh%2FMLbKeRE7cREeDiggKeozk0%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;706&quot; height=&quot;374&quot; data-origin-width=&quot;706&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 글을 적는 시점인 2026년 2월 22일에는 비록 이 커밋이 릴리즈에 들어가지 않아서 적용되지는 않았지만, 커뮤니티를 보면 앤트로픽 회사에서 클로드코드 max모델을 사용하던 유저들의 계정을 정지시킨 흔적이 있음&lt;/li&gt;
&lt;li&gt;raddit에서도 내용 확인이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cghHef/dJMcaaK5iof/tZYkx51ZhKxNqXc21qLQKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cghHef/dJMcaaK5iof/tZYkx51ZhKxNqXc21qLQKk/img.png&quot; data-alt=&quot;https://www.reddit.com/r/ClaudeAI/comments/1qa50sq/anthropic_banning_thirdparty_harnesses_while/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cghHef/dJMcaaK5iof/tZYkx51ZhKxNqXc21qLQKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcghHef%2FdJMcaaK5iof%2FtZYkx51ZhKxNqXc21qLQKk%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;1526&quot; height=&quot;844&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.reddit.com/r/ClaudeAI/comments/1qa50sq/anthropic_banning_thirdparty_harnesses_while/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;임시적 해결&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 에러를 config파일을 수정하여 임시적으로 해결할 수 있지만, 이렇게 해결하여 사용하면 토큰이 많이 쓴다는 의견도 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1742&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFMz8V/dJMcahpULKd/YSEkDZuUjClQZqZltakcoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFMz8V/dJMcahpULKd/YSEkDZuUjClQZqZltakcoK/img.png&quot; data-alt=&quot;https://github.com/anomalyco/opencode/issues/7410&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFMz8V/dJMcahpULKd/YSEkDZuUjClQZqZltakcoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFMz8V%2FdJMcahpULKd%2FYSEkDZuUjClQZqZltakcoK%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;1742&quot; height=&quot;474&quot; data-origin-width=&quot;1742&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/anomalyco/opencode/issues/7410&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;opencode 의존성을 너무 맹신하지 말고, opencode로 클로드코드를 사용하다가 에러가 발생하면 명확한 해결책이 나오지 않는이상 클로드코드 네이티브로 사용을 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://github.com/anomalyco/opencode/commit/973715f3da1839ef2eba62d4140fe7441d539411#diff-23c1b48647ee5935d7825f0f38195a8e018b726e1e331bcc0fcc8f8ce85e4c71L335&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/anomalyco/opencode/commit/973715f3da1839ef2eba62d4140fe7441d539411#diff-23c1b48647ee5935d7825f0f38195a8e018b726e1e331bcc0fcc8f8ce85e4c71L335&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>Anthropic</category>
      <category>claude code</category>
      <category>OpenCode</category>
      <category>오픈코드</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1839</guid>
      <comments>https://ios-development.tistory.com/1839#entry1839comment</comments>
      <pubDate>Wed, 25 Feb 2026 01:03:15 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 스킬 개념 2 - 활용하기 (동적 문자열, 참조, 프론트매터, 자동화 패턴)</title>
      <link>https://ios-development.tistory.com/1837</link>
      <description>&lt;h3 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size23&quot;&gt;동적 문자열 사용 방법 (Variables)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;기술 콘텐츠 내에 동적 값을 주입하여 유연한 대응 가능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,0,0&quot;&gt;$ARGUMENTS&lt;/b&gt;: 기술 호출 시 전달된 모든 인수값. (예: /fix-issue 123 실행 시 123을 데이터로 활용)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4,1,0&quot;&gt;${CLAUDE_SESSION_ID}&lt;/b&gt;: 현재 세션의 고유 식별자. 로깅 및 세션별 파일 생성에 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) skill.md 정의 예시&lt;/p&gt;
&lt;pre id=&quot;code_1771152200222&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: session-logger
description: 이 세션에 대한 활동 로그
---

다음을 logs/${CLAUDE_SESSION_ID}.log에 로깅합니다:

$ARGUMENTS&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;5&quot; data-ke-size=&quot;size23&quot;&gt;skill에서 다른 파일 참조하기&lt;/h3&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;SKILL.md는 핵심 요약에 집중하고, 상세 내용은 별도 파일로 분리하여 컨텍스트 효율화&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;SKILL.md&lt;/b&gt;: 필수 파일. 기술의 개요 및 탐색 가이드 포함 (500줄 이하 권장)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;지원 파일&lt;/b&gt;: 상세 API 명세(reference.md), 사용 예제(examples.md), 유틸리티 스크립트(scripts/) 등으로 구성&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;참조 방식&lt;/b&gt;: 마크다운 링크를 통해 필요할 때만 해당 내용을 클로드가 로드하도록 유도&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 구조)&lt;/p&gt;
&lt;pre id=&quot;code_1771152259650&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;my-skill/
├── SKILL.md (필수 - 개요 및 탐색)
├── reference.md (상세 API 문서 - 필요할 때 로드됨)
├── examples.md (사용 예제 - 필요할 때 로드됨)
└── scripts/
    └── helper.py (유틸리티 스크립트 - 실행됨, 로드되지 않음)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;skill.md 파일)&lt;/p&gt;
&lt;pre id=&quot;code_1771152297033&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;## 추가 리소스

- 완전한 API 세부 정보는 [reference.md](reference.md) 참조
- 사용 예제는 [examples.md](examples.md) 참조&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size23&quot;&gt;호출 및 권한 제어&lt;/h3&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;프론트매터(Frontmatter) 설정을 통해 사용자 및 AI의 실행 권한 관리&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 72px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;설정&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;필드&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;사용자&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;호출&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;AI &lt;/b&gt;&lt;span&gt;&lt;b&gt;자동&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;호출&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;주요&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;용도&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;기본&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;설정&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;일반적인&lt;span&gt; &lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;작업&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;disable-model-invocation: true&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;배포&lt;span&gt;, &lt;/span&gt;커밋&lt;span&gt; &lt;/span&gt;등&lt;span&gt; &lt;/span&gt;의도치&lt;span&gt; &lt;/span&gt;않은&lt;span&gt; &lt;/span&gt;실행&lt;span&gt; &lt;/span&gt;방지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;&lt;b&gt;user-invocable: false&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;불가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&lt;span&gt;배경&lt;span&gt; &lt;/span&gt;지식&lt;span&gt;, &lt;/span&gt;레거시&lt;span&gt; &lt;/span&gt;컨텍스트&lt;span&gt; &lt;/span&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;ex)&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;skill.md&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1771152384600&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: deploy
description: 애플리케이션을 프로덕션에 배포합니다.
disable-model-invocation: true
---

$ARGUMENTS를 프로덕션에 배포합니다:

1. 테스트 스위트 실행
2. 애플리케이션 빌드
3. 배포 대상으로 푸시
4. 배포 성공 확인&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;11&quot; data-ke-size=&quot;size23&quot;&gt;도구 액세스 및 보안&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,0,0&quot;&gt;allowed-tools&lt;/b&gt;: 기술 활성화 시 클로드가 사용할 수 있는 도구(Bash, Read, Write 등)를 특정하여 보안 및 오작동 방지&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12,1,0&quot;&gt;권한 규칙&lt;/b&gt;: /permissions 설정을 통해 특정 기술의 실행 권한을 전역적으로 허용하거나 거부 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) skill.md&lt;/p&gt;
&lt;pre id=&quot;code_1771152447772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: safe-reader
description: 변경하지 않고 파일 읽기
allowed-tools: Read, Grep, Glob
---&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;13&quot; data-ke-size=&quot;size23&quot;&gt;고급 자동화 패턴&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;14&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,0,0&quot;&gt;동적 컨텍스트 주입 (!command)&lt;/b&gt;: 기술 실행 직전 셸 명령어를 수행하여 실시간 데이터를 프롬프트에 삽입 (예: GitHub CLI를 통한 실시간 PR 데이터 추출)&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,1,0&quot;&gt;확장 사고 (Ultrathink)&lt;/b&gt;: 기술 콘텐츠 내 ultrathink 단어 포함 시 클로드의 추론 능력 극대화&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;14,2,0&quot;&gt;서브에이전트 활용 (context: fork)&lt;/b&gt;: 현재 대화 맥락과 분리된 독립된 환경(Explore, Plan 등)에서 기술을 수행하여 결과만 수신&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) skill.md&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 내용: GitHub CLI를 사용하여 라이브 PR 데이터를 가져와 풀 요청을 요약합니다.&amp;nbsp;!gh pr diff&amp;ldquo; 및 기타 명령어가 먼저 실행되고 출력이 프롬프트에 삽입&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1771152501926&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: pr-summary
description: 풀 요청의 변경 사항 요약
context: fork
agent: Explore
allowed-tools: Bash(gh:*)
---

## 풀 요청 컨텍스트
- PR diff: !`gh pr diff`
- PR 댓글: !`gh pr view --comments`
- 변경된 파일: !`gh pr diff --name-only`

## 작업
이 풀 요청을 요약합니다...&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-path-to-node=&quot;15&quot; data-ke-size=&quot;size23&quot;&gt;시각적 출력 생성 (Visual Output)&lt;/h3&gt;
&lt;p data-path-to-node=&quot;16&quot; data-ke-size=&quot;size16&quot;&gt;단순 텍스트 응답을 넘어 외부 스크립트와 결합해 시각화 결과물 도출&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;17&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,0,0&quot;&gt;작동 방식&lt;/b&gt;: 기술 내부에 Python/JS 스크립트를 포함하고 클로드가 이를 실행하도록 지시&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,1,0&quot;&gt;결과물 예시&lt;/b&gt;: 코드베이스 트리 구조 시각화, 테스트 커버리지 보고서, 데이터베이스 스키마 다이어그램 등 브라우저 기반 HTML 파일 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) skill.md&lt;/p&gt;
&lt;pre id=&quot;code_1771152680421&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: codebase-visualizer
description: 코드베이스의 대화형 축소 가능한 트리 시각화를 생성합니다. 새 리포지토리 탐색, 프로젝트 구조 이해 또는 큰 파일 식별 시 사용합니다.
allowed-tools: Bash(python:*)
---

# 코드베이스 시각화기

프로젝트의 파일 구조를 축소 가능한 디렉토리로 보여주는 대화형 HTML 트리 보기를 생성합니다.

## 사용법

프로젝트 루트에서 시각화 스크립트를 실행합니다:

```bash
python ~/.claude/skills/codebase-visualizer/scripts/visualize.py .
```

이렇게 하면 현재 디렉토리에 `codebase-map.html`이 생성되고 기본 브라우저에서 열립니다.

## 시각화가 표시하는 것

- **축소 가능한 디렉토리**: 폴더를 클릭하여 확장/축소
- **파일 크기**: 각 파일 옆에 표시됨
- **색상**: 파일 유형별로 다른 색상
- **디렉토리 합계**: 각 폴더의 집계 크기 표시&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;skill이 너무 자주 트리거 될때 제어 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동으로 skill을 내부적으로 호출될때가 있는데, 이럴땐 프론트 메타에 아래와 같이 해결이 가능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설명을 더 구체적으로 만들기&lt;/li&gt;
&lt;li&gt;&lt;span&gt;수동&lt;/span&gt; &lt;span&gt;호출만&lt;/span&gt; &lt;span&gt;원하면&lt;/span&gt;&amp;nbsp;disable-model-invocation: true&lt;span&gt;를&lt;/span&gt; &lt;span&gt;추가하기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://code.claude.com/docs/ko/skills#claude%EA%B0%80-%EB%AA%A8%EB%93%A0-%EA%B8%B0%EC%88%A0%EC%9D%84-%EB%B3%B4%EC%A7%80-%EB%AA%BB%ED%95%A8&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/skills#claude%EA%B0%80-%EB%AA%A8%EB%93%A0-%EA%B8%B0%EC%88%A0%EC%9D%84-%EB%B3%B4%EC%A7%80-%EB%AA%BB%ED%95%A8&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>skill.md</category>
      <category>동적 문자열</category>
      <category>스킬</category>
      <category>자동화 패턴</category>
      <category>참조</category>
      <category>클로드코드</category>
      <category>프론트매터</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1837</guid>
      <comments>https://ios-development.tistory.com/1837#entry1837comment</comments>
      <pubDate>Wed, 18 Feb 2026 01:21:22 +0900</pubDate>
    </item>
    <item>
      <title>[AI] serena MCP 개념 및 설치 방법</title>
      <link>https://ios-development.tistory.com/1836</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;serena MCP란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Serena&amp;nbsp;MCP(Model&amp;nbsp;Context&amp;nbsp;Protocol)&lt;/b&gt;&amp;nbsp;서버는&amp;nbsp;Oraios&amp;nbsp;AI에서&amp;nbsp;개발&amp;nbsp;및&amp;nbsp;제공하는&amp;nbsp;오픈&amp;nbsp;소스&amp;nbsp;코딩&amp;nbsp;에이전트&amp;nbsp;툴킷&lt;/li&gt;
&lt;li&gt;LSP(Language Server Protocol)을 활용하여 분석함&lt;/li&gt;
&lt;li&gt;LSP는 원래 VSCode나 Xcode 같은 IDE가 언어별(Python, Go, TS 등) 분석 엔진과 소통하기 위해 만든 표준 규격
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,0,0&quot;&gt;구문 분석:&lt;/b&gt; 단순 텍스트가 아니라 Class, Method, Variable 간의 관계를 트리 구조로 이해&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,1,0&quot;&gt;심볼 추적:&lt;/b&gt; find_symbol을 통해 특정 함수가 정의된 위치와 사용된 위치(References)를 즉시 찾아냄&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6,2,0&quot;&gt;효율적인 컨텍스트:&lt;/b&gt; 수만 줄의 코드 중 LLM이 정말로 수정해야 할 정확한 지점만 집어내어 전달&lt;/li&gt;
&lt;li&gt;전체 파일을 읽거나 `grep`과 같은 텍스트 기반 검색에 의존하는 대신, `find_symbol`이나 `insert_after_symbol`과 같은 정교한 도구를 사용하여 복잡한 프로젝트에서도 정확한 컨텍스트를 찾고 코드를 수정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;serena 설치&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;uv 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769693882584&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install uv&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;serena 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769695763367&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 프로젝트 디렉토리 이동
cd ~/work

# Serena 클론
git clone https://github.com/oraios/serena
cd serena

# serena 폴더 추가
mkdir -p ~/.serena

# 설정 파일 복사
cp src/serena/resources/serena_config.template.yml ~/.serena/serena_config.yml&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드코드와 통합&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mcp 서버 설정 (아래 명령어 입력 시 .claude.json에 자동으로 입력됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769696787945&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;claude mcp add serena -- uvx --from git+https://github.com/oraios/serena serena-mcp-server --context ide-assistant --project $(pwd)&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;위에 까지 입력하고 ~/.serena.json 파일 확인&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 serena가 동일한 내용으로 채워져 있지 않다면 serena json부분을 지우고 다시 위 명령어를 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769949252693&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;mcpServers&quot;: {
  &quot;serena&quot;: {
    &quot;type&quot;: &quot;stdio&quot;,
    &quot;command&quot;: &quot;uvx&quot;,
    &quot;args&quot;: [
      &quot;--from&quot;,
      &quot;git+https://github.com/oraios/serena&quot;,
      &quot;serena-mcp-server&quot;,
      &quot;--context&quot;,
      &quot;ide-assistant&quot;,
      &quot;--project&quot;,
      &quot;/Users/jake/Desktop/cobot&quot;
    ],
    &quot;env&quot;: {}
  }
},&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;mcp 서버 띄우기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769948892210&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uvx --from git+https://github.com/oraios/serena serena start-mcp-server&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;claude 코드 챗에 들어가서 /mcp 입력하여 연결된 것 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP8Ld2/dJMcai9Wye6/kzfQvKV8Q9UNwdJzKdK7ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP8Ld2/dJMcai9Wye6/kzfQvKV8Q9UNwdJzKdK7ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP8Ld2/dJMcai9Wye6/kzfQvKV8Q9UNwdJzKdK7ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP8Ld2%2FdJMcai9Wye6%2FkzfQvKV8Q9UNwdJzKdK7ek%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;1020&quot; height=&quot;514&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;serena 관련 파일&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 루트에 생성된 .serena 폴더에 가면 아래와 같은 폴더와 파일이 생성됨 (이 부분은 클로드코드를 사용할때 자동으로 업데이트됨)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;0,0,0&quot; data-index-in-node=&quot;0&quot;&gt;cache&lt;/b&gt;: LSP 기반의 코드 심볼 및 인덱싱 정보를 임시 저장하여 분석 속도를 높이는 공간&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;0,1,0&quot; data-index-in-node=&quot;0&quot;&gt;memories&lt;/b&gt;: 프로젝트의 고유 규칙, 아키텍처 맥락 등 AI가 학습한 장기 지식을 보관하는 곳&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;0,2,0&quot; data-index-in-node=&quot;0&quot;&gt;project.yml&lt;/b&gt;: 관리 중인 프로젝트의 경로, 상태, 메타데이터를 기록한 통합 명세서 파일&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsmwVW/dJMcaajQqwA/hII21Wd9vlMyQJMkSlxYuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsmwVW/dJMcaajQqwA/hII21Wd9vlMyQJMkSlxYuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsmwVW/dJMcaajQqwA/hII21Wd9vlMyQJMkSlxYuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsmwVW%2FdJMcaajQqwA%2FhII21Wd9vlMyQJMkSlxYuk%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;468&quot; height=&quot;232&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/oraios/serena&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/oraios/serena&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>MCP</category>
      <category>Serena</category>
      <category>serena mcp</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1836</guid>
      <comments>https://ios-development.tistory.com/1836#entry1836comment</comments>
      <pubDate>Wed, 11 Feb 2026 00:36:07 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드코드 스킬 개념 1 (Claude Code, Skill.md, 필드)</title>
      <link>https://ios-development.tistory.com/1838</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;스킬이란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클로드코드를 사용할 때 skills 하위 폴더 안에 skill이름을 넣고 md파일을 작성하면 `하나의 기능`으로 사용할 수 있는 것&lt;/li&gt;
&lt;li&gt;폴더 위치는 스콥에따라 3가지로 분류&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;color: #9e9e9e; text-align: start; border-collapse: collapse; width: 100%; height: 54px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개인&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;~/.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 프로젝트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;프로젝트&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 프로젝트만&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플러그인&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;plugin&amp;gt;/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; height: 18px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;플러그인이 활성화된 위치&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;.claude/commands/&lt;/b&gt; 안에 정의된 것들보다도 skill이 더욱 우선순위가 높음&lt;/li&gt;
&lt;li&gt;클로드코드 쓰임 예시
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;skill-name: gen-test-cases: 특정 컴포넌트나 함수에 대한 단위 테스트(Unit Test) 코드 자동 생성.&lt;/li&gt;
&lt;li&gt;write-read-me: 폴더 구조와 코드를 읽고 README.md 초안 작성.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실행 원리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저렇게 skill을 명시해놓으면 알아서 클로드코드가 찾아서 수행하기도 하고, 조금 더 명시적으로는 채팅창에 슬래시를 치고 이름을 검색하면됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) /explain-code 스킬을 만들고 싶은 경우&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스킬 폴더 하위에 디렉토리 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769929965655&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir -p ~/.claude/skills/explain-code&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;skill.md 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769929993351&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/.claude/skills/explain-code/SKILL.md&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;아래처럼 skill.md파일을 작성 (&lt;b&gt;---&lt;/b&gt;를 기준으로 스킬에 대한 설정을 하고 그 하단에 내용을 적는 방식)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;name&lt;/b&gt;: 채팅창에서 &lt;b&gt;/slash-command&lt;/b&gt; 로 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;description&lt;/b&gt;: Claude가 자동으로 로드할 시기를 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769930004919&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: explain-code
description: 시각적 다이어그램과 유추를 사용하여 코드를 설명합니다. 코드가 어떻게 작동하는지 설명하거나, 코드베이스에 대해 가르치거나, 사용자가 &quot;이것이 어떻게 작동하나요?&quot;라고 물을 때 사용합니다.
---

코드를 설명할 때 항상 포함하세요:

1. **유추로 시작**: 코드를 일상 생활의 무언가와 비교합니다.
2. **다이어그램 그리기**: ASCII 아트를 사용하여 흐름, 구조 또는 관계를 표시합니다.
3. **코드 단계별 설명**: 무슨 일이 일어나는지 단계별로 설명합니다.
4. **주의할 점 강조**: 일반적인 실수나 오해는 무엇입니까?

설명을 대화체로 유지합니다. 복잡한 개념의 경우 여러 유추를 사용합니다.&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;/explain-code&lt;/b&gt;로 하거나, &quot;&lt;b&gt;이 코드가 어떻게 작동하나요?&quot; &lt;/b&gt;이렇게&amp;nbsp;사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;skill.md 필드&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 살펴본 대로, &lt;b&gt;---&lt;/b&gt; 라는 기호로 스킬의 성격을 정의할 수 있는데 name과 description 말고도 다른 필드도 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;name&lt;/b&gt;: 채팅창에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;/slash-command&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;description&lt;/b&gt;: Claude가 자동으로 로드할 시기를 결정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;context&lt;/b&gt;: 배포,&amp;nbsp;커밋&amp;nbsp;또는&amp;nbsp;코드&amp;nbsp;생성과&amp;nbsp;같은&amp;nbsp;특정&amp;nbsp;작업에&amp;nbsp;대한&amp;nbsp;단계별&amp;nbsp;지침을&amp;nbsp;제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;disable-model-invocation&lt;/b&gt;: Claude가&amp;nbsp;자동으로&amp;nbsp;트리거하는&amp;nbsp;것을&amp;nbsp;방지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1769930240279&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
name: deploy
description: 애플리케이션을 프로덕션에 배포합니다.
context: fork
disable-model-invocation: true
allowed-tools: Read, Grep
---

애플리케이션 배포:
1. 테스트 스위트 실행
2. 애플리케이션 빌드
3. 배포 대상으로 푸시&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 필드 내용&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;필드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;필수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;설명&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;name&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;기술의&lt;span&gt; &lt;/span&gt;표시&lt;span&gt; &lt;/span&gt;이름입니다&lt;span&gt;. &lt;/span&gt;생략하면&lt;span&gt; &lt;/span&gt;디렉토리&lt;span&gt; &lt;/span&gt;이름을&lt;span&gt; &lt;/span&gt;사용&lt;span&gt;. &lt;/span&gt;소문자&lt;span&gt;, &lt;/span&gt;숫자&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;하이픈만&lt;span&gt; &lt;/span&gt;사용&lt;span&gt; &lt;/span&gt;가능&lt;span&gt;(&lt;/span&gt;최대&lt;span&gt; 64&lt;/span&gt;자&lt;span&gt;).&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;description&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;권장&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;기술이&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;것과&lt;span&gt; &lt;/span&gt;사용&lt;span&gt; &lt;/span&gt;시기&lt;span&gt;. Claude&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;기술을&lt;span&gt; &lt;/span&gt;적용할&lt;span&gt; &lt;/span&gt;시기를&lt;span&gt; &lt;/span&gt;결정&lt;span&gt;. &lt;/span&gt;생략하면&lt;span&gt; &lt;/span&gt;마크다운&lt;span&gt; &lt;/span&gt;콘텐츠의&lt;span&gt; &lt;/span&gt;첫&lt;span&gt; &lt;/span&gt;번째&lt;span&gt; &lt;/span&gt;단락을&lt;span&gt; &lt;/span&gt;사용&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;argument-hint&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;&lt;span&gt;자동&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;완성&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;중에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;표시되는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;힌트로&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;예상&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인수를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;나타냄&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;예&lt;/span&gt;&lt;span&gt;:&amp;nbsp;&lt;/span&gt;[issue-number]&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;또는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;[filename] [format]&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;disable-model-invocation&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;&lt;span&gt;Claude&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;기술을&lt;span&gt; &lt;/span&gt;자동으로&lt;span&gt; &lt;/span&gt;로드하는&lt;span&gt; &lt;/span&gt;것을&lt;span&gt; &lt;/span&gt;방지하려면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;설정&lt;span&gt;.&amp;nbsp;&lt;/span&gt;&lt;span&gt;/name&lt;/span&gt;으로&lt;span&gt; &lt;/span&gt;수동으로&lt;span&gt; &lt;/span&gt;트리거하려는&lt;span&gt; &lt;/span&gt;워크플로우에&lt;span&gt; &lt;/span&gt;사용&lt;span&gt;. &lt;/span&gt;기본값&lt;span&gt;:&amp;nbsp;&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;user-invocable&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메뉴에서&lt;span&gt; &lt;/span&gt;숨기려면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;설정&lt;span&gt;. &lt;/span&gt;사용자가&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;호출해서는&lt;span&gt; &lt;/span&gt;안&lt;span&gt; &lt;/span&gt;되는&lt;span&gt; &lt;/span&gt;배경&lt;span&gt; &lt;/span&gt;지식에&lt;span&gt; &lt;/span&gt;사용&lt;span&gt;. &lt;/span&gt;기본값&lt;span&gt;:&amp;nbsp;&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;allowed-tools&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;이&lt;span&gt; &lt;/span&gt;기술이&lt;span&gt; &lt;/span&gt;활성화되었을&lt;span&gt; &lt;/span&gt;때&lt;span&gt; Claude&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;권한을&lt;span&gt; &lt;/span&gt;요청하지&lt;span&gt; &lt;/span&gt;않고&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;도구&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;model&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;이&lt;span&gt; &lt;/span&gt;기술이&lt;span&gt; &lt;/span&gt;활성화되었을&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;모델&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;context&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;포크된&lt;span&gt; &lt;/span&gt;서브에이전트&lt;span&gt; &lt;/span&gt;컨텍스트에서&lt;span&gt; &lt;/span&gt;실행하려면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;fork&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;설정&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;agent&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;&lt;span&gt;context: fork&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;설정되었을&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;서브에이전트&lt;span&gt; &lt;/span&gt;유형&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;&lt;span&gt;hooks&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 8.25581%;&quot;&gt;&lt;span&gt;아니요&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 73.7209%;&quot;&gt;&lt;span&gt;이&lt;span&gt; &lt;/span&gt;기술의&lt;span&gt; &lt;/span&gt;수명&lt;span&gt; &lt;/span&gt;주기로&lt;span&gt; &lt;/span&gt;범위가&lt;span&gt; &lt;/span&gt;지정된&lt;span&gt; &lt;/span&gt;훅입니다&lt;span&gt;. &lt;/span&gt;구성&lt;span&gt; &lt;/span&gt;형식은&lt;span&gt;&amp;nbsp;&lt;a href=&quot;https://code.claude.com/docs/ko/hooks&quot;&gt;Hooks&lt;/a&gt;&lt;/span&gt;를&lt;span&gt; &lt;/span&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;a href=&quot;https://ios-development.tistory.com/1837&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;포스팅 글&lt;/a&gt;에서 계속)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/ko/skills&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/skills&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>ios</category>
      <category>skill</category>
      <category>skill.md</category>
      <category>SWIFT</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1838</guid>
      <comments>https://ios-development.tistory.com/1838#entry1838comment</comments>
      <pubDate>Wed, 4 Feb 2026 01:21:30 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드 코드 vs 깃헙 코파일럿 (claude code, github copilot)</title>
      <link>https://ios-development.tistory.com/1833</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드&amp;nbsp;코드&amp;nbsp;vs&amp;nbsp;깃헙&amp;nbsp;코파일럿&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클로드 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Anthropic은 2021년, OpenAI의 창립 멤버였던 `다리오 아모데이(Dario Amodei)`와 그 형제들이 설립&lt;/li&gt;
&lt;li&gt;OpenAI가 점점 상업화되고 AI 안전성(Safety)보다 성능 확장에만 치중하는 것에 반대하며 회사를 나옴&lt;/li&gt;
&lt;li&gt;Anthropic의 핵심 가치는 `안전하고 신뢰할 수 있는 AI`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;깃헙 코파일럿
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub은 원래 오픈소스 코드의 저장소였지만, MS 인수 후 `모든 개발 단계에 AI를 심겠다`는 전략을 세우며 2021년 출시된 GitHub Copilot&lt;/li&gt;
&lt;li&gt;MS는 특정 모델(OpenAI)에만 국한되지 않고 Claude나 Gemini 같은 경쟁사 모델도 Copilot 안에서 선택할 수 있게 개방하도록 수정 -&amp;gt; 플랫폼의 힘 강화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;깃헙 코파일럿에서도 클로드 모델을 사용할 수 있는데 클로드 코드와 차이점은?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(깃헙 코파일럿에서 고를 수 있는 클로드 코드 모델들)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;1348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNMhaz/dJMcafMbrjj/kjIJI6UZwPAdgoWH3AROPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNMhaz/dJMcafMbrjj/kjIJI6UZwPAdgoWH3AROPk/img.png&quot; data-alt=&quot;(깃헙 코파일럿에서 고를 수 있는 클로드 코드 모델들)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNMhaz/dJMcafMbrjj/kjIJI6UZwPAdgoWH3AROPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNMhaz%2FdJMcafMbrjj%2FkjIJI6UZwPAdgoWH3AROPk%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;327&quot; height=&quot;825&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;1348&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(깃헙 코파일럿에서 고를 수 있는 클로드 코드 모델들)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비유적으로 클로드 코드와 깃헙 코파일럿은 IDE라고 할 수 있고, 그 IDE에서 돌아가는 가는 model들이 claude sonnet과 같은 것들이라고 이해&lt;/li&gt;
&lt;li&gt;하지만 클로드 코드와 깃헙 코파일럿은 model들을 사용할 때 그 model들의 결과물들을 얻어내는 과정이 다름&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;8&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;GitHub Copilot: 토큰 아끼는 것을 우선&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;전처리 방식:&lt;/b&gt; 개발자가 코드를 작성하는 흐름을 방해하지 않도록 &lt;b data-index-in-node=&quot;35&quot; data-path-to-node=&quot;9,0,0&quot;&gt;속도와 효율&lt;/b&gt;에 최적화&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;알고리즘 특성:&lt;/b&gt; 깃헙만의 알고리즘이 개입하여, 현재 열려 있는 파일이나 최근 수정한 코드 중 관련이 높은 것들만 골라냄&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;토큰 관리:&lt;/b&gt; 전체를 다 보여주기보다는 &lt;b data-index-in-node=&quot;21&quot; data-path-to-node=&quot;9,2,0&quot;&gt;불필요한 부분을 쳐내거나 요약&lt;/b&gt;하여 모델에게 전달. 이는 응답 속도를 높이고 토큰 비용을 아끼는 데 유리하지만, 가끔 아주 멀리 떨어진 파일 간의 복잡한 의존성을 놓칠 수 있다는 단점&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;10&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;Claude Code: 토큰을 아끼지 않고 파악이 우선&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;전처리 방식:&lt;/b&gt; 단순히 보여주는 정보를 수동적으로 받는 것이 아니라, AI가 직접 수사관 처럼 프로젝트를 파악&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;알고리즘 특성:&lt;/b&gt; 특정 파일을 읽으라는 명령이 없어도 스스로 grep(검색)이나 파일 시스템 읽기 도구를 사용해 &lt;b data-index-in-node=&quot;62&quot; data-path-to-node=&quot;11,1,0&quot;&gt;코드 간의 연결 고리를 끝까지 추적&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;토큰 관리:&lt;/b&gt; 토큰 소모가 훨씬 크더라도 `정확한 맥락 파악`을 우선시. 요약된 정보가 아니라 코드의 원본 구조와 전체적인 의존성 그래프를 모델이 직접 보게 함으로써, 대규모 수정 작업 시 발생할 수 있는 부작용을 최소화&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>claude code</category>
      <category>GitHub Copilot</category>
      <category>ios</category>
      <category>깃헙 코파일럿</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1833</guid>
      <comments>https://ios-development.tistory.com/1833#entry1833comment</comments>
      <pubDate>Wed, 28 Jan 2026 01:01:53 +0900</pubDate>
    </item>
    <item>
      <title>[AI] vscode에서 클로드코드 쓰기 - 유용한 기능, 단축키 (init, claude.md</title>
      <link>https://ios-development.tistory.com/1835</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;단축키&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cmd + esc: 포커싱 변경 (에디터 &amp;lt;-&amp;gt; 클로드코드 챗)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드를 드래그하고 cmd + esc하면 클로드코드 채팅창에 해당 코드 위치 참고하게됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;드래그 상태에서도 단순히 포커싱만 변경만 원하는 경우, cmd+2 (클로드코드 챗이 2번째 탭에 있는 경우)&lt;/li&gt;
&lt;li&gt;shift + tab: 에이전트 모드 바꾸기 (아래에서 소개 예정)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;유용한 기능&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cmd + esc로 클로드코드 포커싱하고 난 후 shift + tab하면 모드 변경이 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ask before Edit: 클로드가 코드를 변경하려고 할 때마다 사용자에게 변경 사항을 보여주고 승인을 요청&lt;/li&gt;
&lt;li&gt;Edit Automatically: 사용자의 개별 승인 없이 클로드가 직접 파일을 수정&lt;/li&gt;
&lt;li&gt;Plan mode: 코드를 직접 수정하기 전에, 클로드가 수행할 작업의 단계별 계획을 먼저 세우고 사용자에게 브리핑하는 단계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Jan-11-2026 13-29-33.gif&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mo76s/dJMcahiPsh0/656pP47ZztbtqT6a1tjXy0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mo76s/dJMcahiPsh0/656pP47ZztbtqT6a1tjXy0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mo76s/dJMcahiPsh0/656pP47ZztbtqT6a1tjXy0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/mo76s/dJMcahiPsh0/656pP47ZztbtqT6a1tjXy0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;172&quot; data-filename=&quot;Jan-11-2026 13-29-33.gif&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;/model&quot; 입력 시 다른 모델 선택 가능&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;글을 작성하는 지금은 opus 모델이 가장 비싸고 좋은 모델&lt;/li&gt;
&lt;li&gt;tip) 복잡한 로직을 물어볼땐 Opus를 사용하고 구현같은 것을 할땐 claude-sonnet-4-5 같은 것 사용 추천&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4Uc5G/dJMcafFmo1a/a9eHK8kNglKTolz5JHKV7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4Uc5G/dJMcafFmo1a/a9eHK8kNglKTolz5JHKV7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4Uc5G/dJMcafFmo1a/a9eHK8kNglKTolz5JHKV7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4Uc5G%2FdJMcafFmo1a%2Fa9eHK8kNglKTolz5JHKV7k%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;1346&quot; height=&quot;584&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;18&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;채팅창에 @를 입력하고 폴더나 파일을 입력하면, 그 위치가 입력되어 더욱 구체적이고 명확하게 참조가 가능&lt;/li&gt;
&lt;li&gt;/init: 프로젝트 초기화 및 CLAUDE.md 가이드 생성 (프로젝트 규칙 정의)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CLAUDE.md 파일을 작성하면 ai는 이 CLAUDE.md를 준수하여 작성함&lt;/li&gt;
&lt;li&gt;또는 파일을 그냥 만들어 놓고 거기에 기준들을 작성해놓으면 자동으로 클로드코드가 파악&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvmQLy/dJMcabwbw5a/hTsgWMHEKRr08n9K78SsG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvmQLy/dJMcabwbw5a/hTsgWMHEKRr08n9K78SsG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvmQLy/dJMcabwbw5a/hTsgWMHEKRr08n9K78SsG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvmQLy%2FdJMcabwbw5a%2FhTsgWMHEKRr08n9K78SsG0%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;596&quot; height=&quot;362&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 `/init`으로 입력하면 클로드코드가 알아서 코드를 읽고 여기에 중요한 것을 적어줌.&lt;/li&gt;
&lt;li&gt;이렇게 생긴 .CLAUDE.md는 클로드코드가 내부적으로 코드를 작성하거나 제안을 줄 때, 최우선 지침으로 보기때문에, 프로젝트 협업을 할때 커밋 규칙과 같은 것을 적어 둘 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드코드 지침의 종류&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W0il4/dJMcabbSP8a/RKNC9J8Lj6GpLaQno1MKI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W0il4/dJMcabbSP8a/RKNC9J8Lj6GpLaQno1MKI0/img.png&quot; data-alt=&quot;https://code.claude.com/docs/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W0il4/dJMcabbSP8a/RKNC9J8Lj6GpLaQno1MKI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW0il4%2FdJMcabbSP8a%2FRKNC9J8Lj6GpLaQno1MKI0%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;1516&quot; height=&quot;950&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;950&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://code.claude.com/docs/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>CLAUDE.md</category>
      <category>vscode 클로드코드</category>
      <category>클로드 코드</category>
      <category>클로드코드</category>
      <category>클로드코드 단축키</category>
      <category>클로드코드 유용한 기능</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1835</guid>
      <comments>https://ios-development.tistory.com/1835#entry1835comment</comments>
      <pubDate>Wed, 21 Jan 2026 01:27:44 +0900</pubDate>
    </item>
    <item>
      <title>[AI] 클로드 코드 사용 방법 (vscode에서 클로드 코드 사용 방법)</title>
      <link>https://ios-development.tistory.com/1834</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로드 코드 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1768104330410&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g @anthropic-ai/claude-code&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;vscode 확장&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vscode 오픈 &amp;gt; 확장 &amp;gt; &lt;b&gt;Claude Code for VS Code&lt;/b&gt; 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2382&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xYQ0Y/dJMcabpmWrT/Al3tVqX2IAQsGT3diPyafK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xYQ0Y/dJMcabpmWrT/Al3tVqX2IAQsGT3diPyafK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xYQ0Y/dJMcabpmWrT/Al3tVqX2IAQsGT3diPyafK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxYQ0Y%2FdJMcabpmWrT%2FAl3tVqX2IAQsGT3diPyafK%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;2382&quot; height=&quot;670&quot; data-origin-width=&quot;2382&quot; data-origin-height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IDE 오른쪽에서 생겨난 것을 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqp9Ys/dJMcai23jri/hOODGiJ8rbRTuJyRiycv3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqp9Ys/dJMcai23jri/hOODGiJ8rbRTuJyRiycv3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqp9Ys/dJMcai23jri/hOODGiJ8rbRTuJyRiycv3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbqp9Ys%2FdJMcai23jri%2FhOODGiJ8rbRTuJyRiycv3k%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;1432&quot; height=&quot;612&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단축키 cmd + esc로 오픈&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;1244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfLZuQ/dJMcafSRvE4/6G2e9iouyY6ECv0hQXrZEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfLZuQ/dJMcafSRvE4/6G2e9iouyY6ECv0hQXrZEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfLZuQ/dJMcafSRvE4/6G2e9iouyY6ECv0hQXrZEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfLZuQ%2FdJMcafSRvE4%2F6G2e9iouyY6ECv0hQXrZEk%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;1278&quot; height=&quot;1244&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;1244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 화면에서 Claude.ai Subscription 클릭
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클로드코드 사이트에서 pro plan 구독 버튼을 누르고 결제&lt;/li&gt;
&lt;li&gt;vscode로 돌아와서 다시 클로드 코드 사이트로 갈 수 있는 URL이 있는데 그걸 복사해서 클로드 코드로 가서 확인 누르면 아래처럼 토큰이 보이는 화면 등장&lt;/li&gt;
&lt;li&gt;이 토큰을 복사하여 vscode에 떠있는 클로드 코드 chat 화면에 붙여넣기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;864&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WQbCs/dJMcagYvp3d/Qf3rKw7B4j27K82Zy61vW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WQbCs/dJMcagYvp3d/Qf3rKw7B4j27K82Zy61vW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WQbCs/dJMcagYvp3d/Qf3rKw7B4j27K82Zy61vW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWQbCs%2FdJMcagYvp3d%2FQf3rKw7B4j27K82Zy61vW0%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;1830&quot; height=&quot;864&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;864&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vscode에서 클로드 코드 화면을 닫고 다시 열으면 사용할 수 있는 화면 등장&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2878&quot; data-origin-height=&quot;1446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beH2c8/dJMcadtUCWt/7vv1q0gN1JKWmBkviXe0uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beH2c8/dJMcadtUCWt/7vv1q0gN1JKWmBkviXe0uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beH2c8/dJMcadtUCWt/7vv1q0gN1JKWmBkviXe0uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeH2c8%2FdJMcadtUCWt%2F7vv1q0gN1JKWmBkviXe0uK%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;2878&quot; height=&quot;1446&quot; data-origin-width=&quot;2878&quot; data-origin-height=&quot;1446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 이어서 클로드 코드 유용한 기능, 단축키는 다음 포스팅 글 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://code.claude.com/docs/ko/vs-code&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://code.claude.com/docs/ko/vs-code&lt;/a&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <category>claude code</category>
      <category>ios</category>
      <category>vscode</category>
      <category>클로드 코드 vscode</category>
      <category>클로드코드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1834</guid>
      <comments>https://ios-development.tistory.com/1834#entry1834comment</comments>
      <pubDate>Wed, 14 Jan 2026 01:26:07 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - SwiftUI] 앱 아이콘과 리퀴드글래스 (#Icon Composer, foreground layer, background layer, .icon)</title>
      <link>https://ios-development.tistory.com/1832</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;변경된 앱 아이콘 컨셉&lt;/h4&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpsvSy/dJMcadm5WPA/BqWIzNxzEbrxWBMg7itak1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpsvSy/dJMcadm5WPA/BqWIzNxzEbrxWBMg7itak1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpsvSy/dJMcadm5WPA/BqWIzNxzEbrxWBMg7itak1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpsvSy%2FdJMcadm5WPA%2FBqWIzNxzEbrxWBMg7itak1%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;1342&quot; height=&quot;604&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 이제는 매우 심플하게 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;맥북, 아이폰: 네모난 배경&lt;/li&gt;
&lt;li&gt;애플워치: 동그란 배경&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;1020&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbTYoT/dJMcagEcnqX/3MnnDB6tkS9emBd66lnsG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbTYoT/dJMcagEcnqX/3MnnDB6tkS9emBd66lnsG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbTYoT/dJMcagEcnqX/3MnnDB6tkS9emBd66lnsG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbTYoT%2FdJMcagEcnqX%2F3MnnDB6tkS9emBd66lnsG0%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;1324&quot; height=&quot;1020&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;1020&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 처리하게된 배경에는 `foreground layer`, `background layer`, `.icon`과 관련된 개념이 생겨나서 부터 확립&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Icon Composer (layer와 .icon)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플에서는 앱 아이콘을 정의할때 layer(*층)라는 것을 두어서 이것을 사용하여 앱 아이콘을 표현함&lt;/li&gt;
&lt;li&gt;층을 두어서 입체적으로 표현하려는것이 목적&lt;/li&gt;
&lt;li&gt;층(layer)들을 합쳐놓은(Composer)것을 Icon Composer라고 지칭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2354&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhWqZg/dJMcai20BxR/9GKcHDaik27GtaX9jTLme1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhWqZg/dJMcai20BxR/9GKcHDaik27GtaX9jTLme1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhWqZg/dJMcai20BxR/9GKcHDaik27GtaX9jTLme1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhWqZg%2FdJMcai20BxR%2F9GKcHDaik27GtaX9jTLme1%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;2354&quot; height=&quot;772&quot; data-origin-width=&quot;2354&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 개념에 의해, 이제 여러가지의 앱 아이콘 제작이 없이, 단순히 각 layer를 표현하는 이미지만 애셋에 등록하는 형태&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;Icon Composer 적용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/download/all/?q=Icon%20Composer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;애플 developer 사이트&lt;/a&gt; &amp;gt; 다운로드 &amp;gt; Icon Composer 검색&lt;/li&gt;
&lt;li&gt;아래 파일 설치&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAmjV3/dJMcaiIIQPR/Tfo91qbYSh2yPVspePr6J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAmjV3/dJMcaiIIQPR/Tfo91qbYSh2yPVspePr6J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAmjV3/dJMcaiIIQPR/Tfo91qbYSh2yPVspePr6J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAmjV3%2FdJMcaiIIQPR%2FTfo91qbYSh2yPVspePr6J1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2236&quot; height=&quot;1476&quot; data-origin-width=&quot;2236&quot; data-origin-height=&quot;1476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오픈&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2274&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1Lwff/dJMcadN9WGp/Wk0s6kDOe4b4ioR1hVdsR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1Lwff/dJMcadN9WGp/Wk0s6kDOe4b4ioR1hVdsR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1Lwff/dJMcadN9WGp/Wk0s6kDOe4b4ioR1hVdsR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1Lwff%2FdJMcadN9WGp%2FWk0s6kDOe4b4ioR1hVdsR0%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;2274&quot; height=&quot;1800&quot; data-origin-width=&quot;2274&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;layer를 쌓으려면 좌측하단 &amp;gt; 플러스 버튼을 눌러서 group 이나 image 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vCalq/dJMcahXplrq/i8bkqKVsdutmVTzSEgTa31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vCalq/dJMcahXplrq/i8bkqKVsdutmVTzSEgTa31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vCalq/dJMcahXplrq/i8bkqKVsdutmVTzSEgTa31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvCalq%2FdJMcahXplrq%2Fi8bkqKVsdutmVTzSEgTa31%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;1144&quot; height=&quot;1704&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1704&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이미지 추가 하면 위에 layer처럼 쌓임)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;1718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWcjGo/dJMcaacTabu/dihn5amq4EP6suAU4ncdk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWcjGo/dJMcaacTabu/dihn5amq4EP6suAU4ncdk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWcjGo/dJMcaacTabu/dihn5amq4EP6suAU4ncdk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWcjGo%2FdJMcaacTabu%2Fdihn5amq4EP6suAU4ncdk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2268&quot; height=&quot;1718&quot; data-origin-width=&quot;2268&quot; data-origin-height=&quot;1718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 용어 참고 (&lt;a href=&quot;https://developer.apple.com/documentation/Xcode/creating-your-app-icon-using-icon-composer&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/documentation/Xcode/creating-your-app-icon-using-icon-composer&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1160&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkc6ol/dJMcaa41GD3/ocxMRc5l77bEKuvpeExx1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkc6ol/dJMcaa41GD3/ocxMRc5l77bEKuvpeExx1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkc6ol/dJMcaa41GD3/ocxMRc5l77bEKuvpeExx1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbkc6ol%2FdJMcaa41GD3%2FocxMRc5l77bEKuvpeExx1k%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;1160&quot; height=&quot;1202&quot; data-origin-width=&quot;1160&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장 (cmd + s)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4R2J6/dJMcadUV35A/5DS5WEHVRFmyNSL6BJas6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4R2J6/dJMcadUV35A/5DS5WEHVRFmyNSL6BJas6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4R2J6/dJMcadUV35A/5DS5WEHVRFmyNSL6BJas6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4R2J6%2FdJMcadUV35A%2F5DS5WEHVRFmyNSL6BJas6K%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;974&quot; height=&quot;766&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 파일을 Xcode 프로젝트 폴더에다가 드래그 앤 드롭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2164&quot; data-origin-height=&quot;1644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5qviW/dJMcaiBWBYI/gmGtoUsmk7NNUMnfviOlEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5qviW/dJMcaiBWBYI/gmGtoUsmk7NNUMnfviOlEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5qviW/dJMcaiBWBYI/gmGtoUsmk7NNUMnfviOlEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5qviW%2FdJMcaiBWBYI%2FgmGtoUsmk7NNUMnfviOlEk%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;2164&quot; height=&quot;1644&quot; data-origin-width=&quot;2164&quot; data-origin-height=&quot;1644&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주의) Assets 폴더 안에 넣는것이 아닌 그 밖에다 배치해야함&lt;/li&gt;
&lt;li&gt;Xcode &amp;gt; Target &amp;gt; App Icon에 &quot;myIcon&quot; 입력하고 App Icons sources에 체크하면 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Li4a6/dJMcai9MvYc/kKvHIGLI2xWEHlsUStrpBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Li4a6/dJMcai9MvYc/kKvHIGLI2xWEHlsUStrpBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Li4a6/dJMcai9MvYc/kKvHIGLI2xWEHlsUStrpBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLi4a6%2FdJMcai9MvYc%2FkKvHIGLI2xWEHlsUStrpBk%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;2272&quot; height=&quot;772&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경된 것 확인 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;1532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1ZP2v/dJMcahb0Gat/xNKbIBjRgqaYGBKxpVFm50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1ZP2v/dJMcahb0Gat/xNKbIBjRgqaYGBKxpVFm50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1ZP2v/dJMcahb0Gat/xNKbIBjRgqaYGBKxpVFm50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1ZP2v%2FdJMcahb0Gat%2FxNKbIBjRgqaYGBKxpVFm50%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;708&quot; height=&quot;1532&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;1532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://youtu.be/l-9tYm0U998&quot;&gt;https://youtu.be/l-9tYm0U998&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/icon-composer/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/icon-composer/&lt;/a&gt;&lt;/p&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>icon composer</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>리퀴드글래스</category>
      <category>앱 아이콘</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1832</guid>
      <comments>https://ios-development.tistory.com/1832#entry1832comment</comments>
      <pubDate>Wed, 7 Jan 2026 01:36:51 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - SwiftUI] Sticky Header 구현 방법 (Sticky 헤더, List 사용)</title>
      <link>https://ios-development.tistory.com/1831</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;cf) LazyVStack해서 구현 방법 포스팅 글은 이 링크의 포스팅 글 참고: &lt;a href=&quot;https://ios-development.tistory.com/1760&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ios-development.tistory.com/1760&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Dec-29-2025 15-17-24.gif&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; data-alt=&quot;List로 구현한 Sticky Header&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;760&quot; data-filename=&quot;Dec-29-2025 15-17-24.gif&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;List로 구현한 Sticky Header&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;StickyHeader 구현 아이디어&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;StickyHeader를 순수 직접 구현하려면 많은 작업이 들겠지만, SwiftUI에서 List안에 &lt;b&gt;&lt;span&gt;Section&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;를 이용하면, 스크롤 시 자동으로 위에 걸쳐지는 효과를 사용하면 구현하기가 매우 쉬움&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;단, List의 속성에 &lt;/span&gt;&lt;b&gt;.&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;listStyle&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(.&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;plain&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;b&gt;)&lt;/b&gt;을 해줘야 section으로 넣었던 UI들이 sticky header로 동작함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;구현&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;List 선언&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989280488&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {&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;sticky header 위쪽에 위치할 뷰를 넣어주기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 사진에서 Top Content 부분&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AQbhB/dJMcabixtXi/CBnkns4AHyUOBZLwwu09U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AQbhB/dJMcabixtXi/CBnkns4AHyUOBZLwwu09U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AQbhB/dJMcabixtXi/CBnkns4AHyUOBZLwwu09U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAQbhB%2FdJMcabixtXi%2FCBnkns4AHyUOBZLwwu09U0%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;425&quot; height=&quot;352&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VStack 안에 넣기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989355255&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                // 1. 상단 콘텐츠 (Header가 고정되기 전 함께 스크롤됨)
                VStack {
                    Text(&quot;Top Content&quot;)
                        .font(.largeTitle)
                        .padding()
                        .background(Color.green)
                        .cornerRadius(10)
                }
                .frame(maxWidth: .infinity)
                .padding()
                .listRowSeparator(.hidden) // 구분선 제거
                .listRowInsets(EdgeInsets()) // 좌우 여백 제거&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;여기 아래에 Sticky Header가 붙어야 하므로 &lt;b&gt;Section(header:)&lt;/b&gt;라는 것을 넣기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989412389&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                // 상단 콘텐츠 (Header가 고정되기 전 함께 스크롤됨)
                VStack {
                    ...
                }

                // Sticky Header가 포함된 섹션1
                Section(header: MyStickyHeader()) {
                    ForEach(0..&amp;lt;50) { index in
                        Text(&quot;Item \(index)&quot;)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.blue.opacity(0.3))
                            .cornerRadius(10)
                    }
                    .listRowSeparator(.hidden)
                    .listRowInsets(EdgeInsets(top: 5, leading: 16, bottom: 5, trailing: 16))
                }

...

struct MyStickyHeader: View {
    var body: some View {
        Text(&quot;Sticky Header&quot;)
            .font(.largeTitle)
            .bold()
            .frame(maxWidth: .infinity)
            .background([Color.red, Color.blue, Color.green].randomElement()!)
            .foregroundColor(.white)
    }
}&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;여기까지 구현하면 StickyHeader 부분의 상단에 아래처럼 padding이 생기므로 이 패딩을 없애는 코드도 따로 처리가 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UHkDn/dJMcacuYAyr/hjXgHKCQ36mAVcad2s7kt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UHkDn/dJMcacuYAyr/hjXgHKCQ36mAVcad2s7kt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UHkDn/dJMcacuYAyr/hjXgHKCQ36mAVcad2s7kt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUHkDn%2FdJMcacuYAyr%2FhjXgHKCQ36mAVcad2s7kt0%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;698&quot; height=&quot;572&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이것은 header 구현한 코드에 &lt;b&gt;.listRowInsets(EdgeInsets())&lt;/b&gt;를 추가하여 해결 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989534922&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct MyStickyHeader: View {
    var body: some View {
        Text(&quot;Sticky Header&quot;)
            .font(.largeTitle)
            .bold()
            .frame(maxWidth: .infinity)
            .background([Color.red, Color.blue, Color.green].randomElement()!)
            .foregroundColor(.white)
            .listRowInsets(EdgeInsets()) // &amp;lt;- header의 padding 제거
    }
}&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;또 다른 sticky header를 넣고 싶다면 동일하게 넣기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989638422&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                // 상단 콘텐츠 (Header가 고정되기 전 함께 스크롤됨)
                VStack {
                    ...
                }

                // Sticky Header가 포함된 섹션1
                Section(header: MyStickyHeader()) {
                    ForEach(0..&amp;lt;50) { index in
                        Text(&quot;Item \(index)&quot;)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.blue.opacity(0.3))
                            .cornerRadius(10)
                    }
                    .listRowSeparator(.hidden)
                    .listRowInsets(EdgeInsets(top: 5, leading: 16, bottom: 5, trailing: 16))
                }

                // Sticky Header가 포함된 섹션2
                Section(header: MyStickyHeader()) {
                    ForEach(0..&amp;lt;50) { index in
                        Text(&quot;Item \(index)&quot;)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.blue.opacity(0.3))
                            .cornerRadius(10)
                    }
                    .listRowSeparator(.hidden)
                    .listRowInsets(EdgeInsets(top: 5, leading: 16, bottom: 5, trailing: 16))
                }
...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기까지 완성된 코드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989771076&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                // 1. 상단 콘텐츠 (Header가 고정되기 전 함께 스크롤됨)
                VStack {
                    ...
                }

                // 2. Sticky Header가 포함된 섹션1
                Section(header: MyStickyHeader()) {
                    ...
                }
                
                // 2. Sticky Header가 포함된 섹션2
                Section(header: MyStickyHeader()) {
                    ...
                }
            }
            .listStyle(.plain) // 중요: Sticky 효과를 위한 스타일
        }
    }
}&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;여기까지 하고 실행시켜보면 navigation bar 부분이 투명해서 뒤에 셀이 보여짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1086&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HlC6r/dJMcacV2tZv/elEknZLlBzxN44iaLLcn2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HlC6r/dJMcacV2tZv/elEknZLlBzxN44iaLLcn2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HlC6r/dJMcacV2tZv/elEknZLlBzxN44iaLLcn2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHlC6r%2FdJMcacV2tZv%2FelEknZLlBzxN44iaLLcn2k%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;483&quot; height=&quot;725&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1086&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 navigationBar가 항상 보여지게하고, Color를 white로 바꾸는 코드가 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1766989885041&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                ...
            }
            .listStyle(.plain) // 중요: Sticky 효과를 위한 스타일
            .toolbarBackground(Color.white, for: .navigationBar) // 배경색 지정 (코드 없으면 스크롤 될 때 뒤의 셀들이 보임)
            .toolbarBackground(.visible, for: .navigationBar)   // 항상 보이게 설정 (코드 없으면 스크롤 될 때 뒤의 셀들이 보임)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(완성)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Dec-29-2025 15-17-24.gif&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; data-alt=&quot;List로 구현한 Sticky Header&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/C8mNR/dJMcaajCZkn/F1bQ3xkplCLxNFBfnq92dK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;760&quot; data-filename=&quot;Dec-29-2025 15-17-24.gif&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;List로 구현한 Sticky Header&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 전체 코드&lt;/p&gt;
&lt;pre id=&quot;code_1766989090387&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            ListStickyHeaderView()
        }
    }
}

struct ListStickyHeaderView: View {
    var body: some View {
        NavigationView {
            List {
                // 1. 상단 콘텐츠 (Header가 고정되기 전 함께 스크롤됨)
                VStack {
                    Text(&quot;Top Content&quot;)
                        .font(.largeTitle)
                        .padding()
                        .background(Color.green)
                        .cornerRadius(10)
                }
                .frame(maxWidth: .infinity)
                .padding()
                .listRowSeparator(.hidden) // 구분선 제거
                .listRowInsets(EdgeInsets()) // 좌우 여백 제거

                // 2. Sticky Header가 포함된 섹션1
                Section(header: MyStickyHeader()) {
                    ForEach(0..&amp;lt;50) { index in
                        Text(&quot;Item \(index)&quot;)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.blue.opacity(0.3))
                            .cornerRadius(10)
                    }
                    .listRowSeparator(.hidden)
                    .listRowInsets(EdgeInsets(top: 5, leading: 16, bottom: 5, trailing: 16))
                }
                
                // 2. Sticky Header가 포함된 섹션2
                Section(header: MyStickyHeader()) {
                    ForEach(0..&amp;lt;50) { index in
                        Text(&quot;Item \(index)&quot;)
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.blue.opacity(0.3))
                            .cornerRadius(10)
                    }
                    .listRowSeparator(.hidden)
                    .listRowInsets(EdgeInsets(top: 5, leading: 16, bottom: 5, trailing: 16))
                }
            }
            .listStyle(.plain) // 중요: Sticky 효과를 위한 스타일
            .toolbarBackground(Color.white, for: .navigationBar) // 배경색 지정 (코드 없으면 스크롤 될 때 뒤의 셀들이 보임)
            .toolbarBackground(.visible, for: .navigationBar)   // 항상 보이게 설정 (코드 없으면 스크롤 될 때 뒤의 셀들이 보임)
        }
    }
}

struct MyStickyHeader: View {
    var body: some View {
        Text(&quot;Sticky Header&quot;)
            .font(.largeTitle)
            .bold()
            .frame(maxWidth: .infinity)
            .background([Color.red, Color.blue, Color.green].randomElement()!)
            .foregroundColor(.white)
            .listRowInsets(EdgeInsets()) // 3. header의 padding 제거
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>ios</category>
      <category>list</category>
      <category>StickyHeader</category>
      <category>swiftUI</category>
      <category>스티키 헤더</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1831</guid>
      <comments>https://ios-development.tistory.com/1831#entry1831comment</comments>
      <pubDate>Wed, 31 Dec 2025 01:15:41 +0900</pubDate>
    </item>
    <item>
      <title>[WWDC2025] SwiftUI 최적화 프로파일링 - Optimize SwiftUI performance with Instruments (5)</title>
      <link>https://ios-development.tistory.com/1830</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;WWDC 에는 나오지 않지만 중요한 정보&amp;gt;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #222222; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;SwiftUI Instruments 에 중요한 것&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SwiftUI Instruments를 보면 빨간선과 주황선이 보이는데, 이 정보들은 중요한 것임
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(아래 사진 관련 내용: &lt;a href=&quot;https://ios-development.tistory.com/1815&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ios-development.tistory.com/1815&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1942&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eulPLd/dJMcadHkzHK/vayvDvQeyvTr3zAxCUPCn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eulPLd/dJMcadHkzHK/vayvDvQeyvTr3zAxCUPCn0/img.png&quot; data-alt=&quot;https://wwdcnotes.com/documentation/wwdcnotes/wwdc25-256-whats-new-in-swiftui/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eulPLd/dJMcadHkzHK/vayvDvQeyvTr3zAxCUPCn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeulPLd%2FdJMcadHkzHK%2FvayvDvQeyvTr3zAxCUPCn0%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;1942&quot; height=&quot;756&quot; data-origin-width=&quot;1942&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://wwdcnotes.com/documentation/wwdcnotes/wwdc25-256-whats-new-in-swiftui/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size20&quot;&gt;빨간색 선 기준&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;3&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,0,0&quot;&gt;기준:&lt;/b&gt; View의 body 계산 시간이 &lt;b&gt;1.0ms&lt;/b&gt;를 초과할 때 표시&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,1,0&quot;&gt;의미:&lt;/b&gt; 매우 심각한 성능 저하 상태&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;3,2,0&quot;&gt;영향:&lt;/b&gt; 120Hz 디스플레이(ProMotion) 환경에서 프레임당 가용 시간은 약 8.3ms인데, 뷰 하나 그리는 데 1ms를 넘겨버리면 실제 렌더링 루틴 전체가 꼬이며 눈에 띄는 &lt;b&gt;Hitch(버벅임)&lt;/b&gt;가 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;4&quot; data-ke-size=&quot;size20&quot;&gt;주황색 선 기준&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;기준:&lt;/b&gt; View의 body 계산 시간이 &lt;b&gt;0.5ms&lt;/b&gt;를 초과할 때 표시&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;의미:&lt;/b&gt; 성능 저하 주의 단계&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;영향:&lt;/b&gt; 당장 화면이 멈추지는 않더라도, 이런 뷰가 리스트(List/ScrollView) 내부에 많아지면 누적 연산 시간이 늘어나 프레임 드랍의 직접적인 원인이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size20&quot;&gt;수치의 의미&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SwiftUI의 &lt;b data-index-in-node=&quot;9&quot; data-path-to-node=&quot;7,0,0&quot;&gt;Render Loop&lt;/b&gt;는 단순히 body만 읽고 끝나는 게 아님&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;Body 계산 &amp;rarr; 레이아웃 결정 &amp;rarr; 뷰 트리 비교(Diffing) &amp;rarr; GPU Commit&lt;/b&gt; 과정을 한 프레임 안에 다 끝내야 하기 때문&lt;/li&gt;
&lt;li&gt;즉, body 연산에서 이미 1ms를 써버리면 나머지 과정을 수행할 시간이 부족해 시스템 전체 성능에 과부하를 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과부하 예시)&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;1,0,0&quot;&gt;리스트 누적 연산:&lt;/b&gt; 화면에 셀 10개가 보일 때 각 셀의 body가 1ms라면, 순수 연산만 &lt;b data-index-in-node=&quot;61&quot; data-path-to-node=&quot;1,0,0&quot;&gt;10ms&lt;/b&gt;가 소요되어 ProMotion 기준(8.3ms)을 즉시 초과하고 스크롤 렉을 유발함&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;1,1,0&quot;&gt;프레임 점유율:&lt;/b&gt; 120Hz 환경에서 뷰 하나가 &lt;b data-index-in-node=&quot;26&quot; data-path-to-node=&quot;1,1,0&quot;&gt;1ms&lt;/b&gt;를 쓰면 전체 가용 시간의 &lt;b data-index-in-node=&quot;44&quot; data-path-to-node=&quot;1,1,0&quot;&gt;12% 이상&lt;/b&gt;을 혼자 점유하게 되어, 레이아웃 및 GPU 렌더링 등 후속 공정의 시간을 뺏음&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;1,2,0&quot;&gt;복합 계층의 위기:&lt;/b&gt; 상위 뷰 변경으로 하위 뷰들이 줄줄이 재계산될 때, 각 서브뷰가 &lt;b&gt;0.5ms&lt;/b&gt;씩만 잡아먹어도 전체 렌더링 파이프라인이 금방 마비됨&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>최적화하기</category>
      <category>ios</category>
      <category>swiftUI</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1830</guid>
      <comments>https://ios-development.tistory.com/1830#entry1830comment</comments>
      <pubDate>Wed, 24 Dec 2025 01:32:42 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - SwfitUI] 탭했을 때 키보드 내리는 법 (simultaneousGesture를 쓸때 주의할 점)</title>
      <link>https://ios-development.tistory.com/1829</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;탭했을 때 키보드 내리기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Dec-14-2025 21-18-40.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q9Hmn/dJMcai9EUw4/Vex76PK6t5oBrK7qkRpKS0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q9Hmn/dJMcai9EUw4/Vex76PK6t5oBrK7qkRpKS0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q9Hmn/dJMcai9EUw4/Vex76PK6t5oBrK7qkRpKS0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/q9Hmn/dJMcai9EUw4/Vex76PK6t5oBrK7qkRpKS0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;888&quot; data-filename=&quot;Dec-14-2025 21-18-40.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 제스처도 동시에 동작하게끔 하기 위해 보통 아래처럼 simultaneousGesture를 사용하여 tapGesture 이벤트를 얻어서 isFocused = false로 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765714566889&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    @State private var text: String = &quot;&quot;
    @FocusState private var isFocused: Bool

    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                TextField(&quot;텍스트를 입력하세요&quot;, text: $text)
                    .textFieldStyle(.roundedBorder)
                    .focused($isFocused)

                ...
            }
            .padding()
        }
        .simultaneousGesture(
            TapGesture().onEnded {
                isFocused = false
            }
        )
        .simultaneousGesture(
            DragGesture().onChanged { _ in
                isFocused = false
            }
        )
    }
}&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;하지만 simultaneousGesture를 사용하면 아래처럼 자기 자신의 텍스트필드를 탭했을때도 키보드가 내려감&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Dec-14-2025 21-20-32.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFiz8V/dJMcaiBORBH/AVFssFwPd7aPhmgS5KHFr1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFiz8V/dJMcaiBORBH/AVFssFwPd7aPhmgS5KHFr1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFiz8V/dJMcaiBORBH/AVFssFwPd7aPhmgS5KHFr1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dFiz8V/dJMcaiBORBH/AVFssFwPd7aPhmgS5KHFr1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;888&quot; data-filename=&quot;Dec-14-2025 21-20-32.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;simultaneousGesture가 아니라 tapGesture를 사용하면 텍스트 필드 자기 자신을 탭해도 여전히 유지되어 원하는 동작이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Dec-14-2025 21-21-04.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhiQ0S/dJMcagxhksv/mhUGMDYogw1McwF1kQvUsk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhiQ0S/dJMcagxhksv/mhUGMDYogw1McwF1kQvUsk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhiQ0S/dJMcagxhksv/mhUGMDYogw1McwF1kQvUsk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dhiQ0S/dJMcagxhksv/mhUGMDYogw1McwF1kQvUsk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;888&quot; data-filename=&quot;Dec-14-2025 21-21-04.gif&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;888&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;simultaneousGesture 사용과 onTapGesture 동작이 다른 이유?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우선순위가 다르기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;simultaneousGesture를 사용할 때 주의할 점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;simultaneousGesture
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자식과 병렬로 모두 인식 &amp;rarr; 컨트롤 동작을 유지하면서 부모 처리도 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;onTapGesture
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자식 제스처와 경쟁하며 자식의 우선순위가 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;때문에, simultaneousGesture를 사용하면 우선순위가 다 동일해지고, onTapGesture를 사용하면 자식의 우선순위가 높아진다는 것을 알 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체 코드&lt;/h4&gt;
&lt;pre id=&quot;code_1765715101784&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    @State private var text: String = &quot;&quot;
    @FocusState private var isFocused: Bool

    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                TextField(&quot;텍스트를 입력하세요&quot;, text: $text)
                    .textFieldStyle(.roundedBorder)
                    .focused($isFocused)

                ForEach(0..&amp;lt;20, id: \.self) { idx in
                    Text(&quot;Row \(idx)&quot;)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .padding(.vertical, 8)
                }
            }
            .padding()
        }
//        .simultaneousGesture(
//            TapGesture().onEnded {
//                isFocused = false
//            }
//        )
        .simultaneousGesture(
            DragGesture().onChanged { _ in
                isFocused = false
            }
        )
        .onTapGesture {
            isFocused = false
        }
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>ios</category>
      <category>keyboard 내리기</category>
      <category>simultaneousgesture</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>TapGesture</category>
      <category>키보드 내리는 방법</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1829</guid>
      <comments>https://ios-development.tistory.com/1829#entry1829comment</comments>
      <pubDate>Wed, 17 Dec 2025 01:24:32 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 전체빌드와 증분빌드 차이점</title>
      <link>https://ios-development.tistory.com/1828</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체빌드 개념&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단어 그대로 캐싱 없이, a부터 z까지 모든 파일을 빌드하는 것&amp;nbsp;&lt;/li&gt;
&lt;li&gt;cf) 빌드란?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드들을 실행 가능한 형태로 메모리에 올리는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;1154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SG5nR/dJMcahiB761/RSPVROT8t3YJAgiDjkh6E1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SG5nR/dJMcahiB761/RSPVROT8t3YJAgiDjkh6E1/img.png&quot; data-alt=&quot;https://ios-development.tistory.com/1336&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SG5nR/dJMcahiB761/RSPVROT8t3YJAgiDjkh6E1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSG5nR%2FdJMcahiB761%2FRSPVROT8t3YJAgiDjkh6E1%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;521&quot; height=&quot;682&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;1154&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://ios-development.tistory.com/1336&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;증분빌드 개념&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;증분&amp;nbsp;빌드(Incremental&amp;nbsp;Build)는&amp;nbsp;&amp;ldquo;변화가&amp;nbsp;영향을&amp;nbsp;미치는&amp;nbsp;범위만&amp;nbsp;찾아서&amp;nbsp;필요한&amp;nbsp;파일만&amp;nbsp;재컴파일&amp;rdquo;하는&amp;nbsp;방식&lt;/li&gt;
&lt;li&gt;Xcode는&amp;nbsp;이를&amp;nbsp;위해&amp;nbsp;&amp;ldquo;의존성&amp;nbsp;그래프(Dependency&amp;nbsp;Graph)&amp;rdquo;와&amp;nbsp;&amp;ldquo;인터페이스&amp;nbsp;파일(.swiftinterface&amp;nbsp;/&amp;nbsp;.dia)&amp;rdquo;을&amp;nbsp;사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;증분빌드 원리&lt;/span&gt;&lt;/h4&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: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;빌드 시스템은 파일마다 해시(hash) 또는 timestamp를 기록해 두고 있다가 사용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1765088638637&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FileA.swift &amp;rarr; 해시값 0xA2B3 
FileB.swift &amp;rarr; 해시값 0xC883&lt;/code&gt;&lt;/pre&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;Swift는 모든 .swift 파일 내부의 타입, 프로토콜, extension 등을 분석해 파일 간의 의존성 그래프를 만듦
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;879&quot; data-end=&quot;949&quot;&gt;User.swift를 변경하면 &amp;rarr; ProfileView.swift, SettingsView.swift도 다시 빌드되어야 함&lt;/li&gt;
&lt;li data-start=&quot;950&quot; data-end=&quot;997&quot;&gt;하지만 SettingsView 안에서 User를 쓰지 않으면 &amp;rarr; 건드릴 필요 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1765088693574&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;User.swift &amp;larr; ProfileView.swift &amp;larr; SettingsView.swift&lt;/code&gt;&lt;/pre&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;Swift 컴파일러는 각 파일의 &lt;b&gt;인터페이스&lt;/b&gt; 파일을 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1193&quot; data-start=&quot;1191&quot; data-ke-size=&quot;size16&quot;&gt;예) 인터페이스 파일 (인터페이스: Stored property, function signature, protocol 정의)&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1313&quot; data-start=&quot;1195&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1313&quot; data-start=&quot;1240&quot;&gt;
&lt;tr data-end=&quot;1285&quot; data-start=&quot;1240&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1255&quot; data-start=&quot;1240&quot;&gt;MyType.swift&lt;/td&gt;
&lt;td data-end=&quot;1285&quot; data-start=&quot;1255&quot; data-col-size=&quot;sm&quot;&gt;MyType~partial.swiftmodule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1313&quot; data-start=&quot;1286&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1294&quot; data-start=&quot;1286&quot;&gt;외부 모듈&lt;/td&gt;
&lt;td data-end=&quot;1313&quot; data-start=&quot;1294&quot; data-col-size=&quot;sm&quot;&gt;.swiftinterface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1452&quot; data-start=&quot;1427&quot;&gt;만약? 함수 내부(body)만 바뀌면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1452&quot; data-start=&quot;1427&quot;&gt;인터페이스는 그대로 &amp;rarr; 다른 파일은 영향 없음 &amp;rarr; &lt;b&gt;증분 빌드 가능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1535&quot; data-start=&quot;1495&quot;&gt;stored property, public API 변경되면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1535&quot; data-start=&quot;1495&quot;&gt;인터페이스가 바뀜 &amp;rarr; 영향을 받는 모든 파일 재컴파일 &amp;rarr; &lt;b&gt;증분 빌드 불가&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체 빌드로 되는 경우?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다음 중 하나라도 일어나면 전체빌드로 됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런 경우엔 &amp;ldquo;의존성 그래프&amp;rdquo; 자체가 다시 계산되기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765088859504&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;모듈 public interface 변경
struct stored property 변경
protocol 변경
extension에 public method 추가
Swift version 변경
optimization level 변경
Package / Pod 업데이트
DerivedData 삭제
Build setting 변경
bridging header(ObjC) 변경&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;증분빌드 되었는지 유무는 빌드를 끝내고 결과물이 나오는 xcresult 파일에서 확인 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;xcresult 파일 개념: &lt;a href=&quot;https://ios-development.tistory.com/1827&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ios-development.tistory.com/1827&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 증분빌드인지 알아내는 방법&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;xcresult 결과를 보면 핵심 파일인 ContentView.swift 파일이 있는데, 이 파일 이컴파일 될때 wasFetchedFromCache가 true인 것을 보면 캐싱되어서 증분빌드 되었다는 것을 추측 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WA7vX/dJMcahpoq0V/Vg0maAYoMyzhCOpk8xKq30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WA7vX/dJMcahpoq0V/Vg0maAYoMyzhCOpk8xKq30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WA7vX/dJMcahpoq0V/Vg0maAYoMyzhCOpk8xKq30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWA7vX%2FdJMcahpoq0V%2FVg0maAYoMyzhCOpk8xKq30%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;1810&quot; height=&quot;404&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>Xcode</category>
      <category>전체빌드</category>
      <category>증분빌드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1828</guid>
      <comments>https://ios-development.tistory.com/1828#entry1828comment</comments>
      <pubDate>Wed, 10 Dec 2025 01:36:41 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 빌드 로그 json형태로 뽑아보기 (xcresult, xcactivitylog, XCLogParser)</title>
      <link>https://ios-development.tistory.com/1827</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;xcactivitylog&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode가 빌드/테스트/아카이브할 때 생성되는 빌드 로그의 원본 파일&lt;br /&gt;(= Xcode UI에서 보는 Build Log 화면(⌘ + 9)의 실제 데이터 파일)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bydWkK/dJMcadNXpwn/JkUGwFey3HiJhJ5WKKN7t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bydWkK/dJMcadNXpwn/JkUGwFey3HiJhJ5WKKN7t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bydWkK/dJMcadNXpwn/JkUGwFey3HiJhJ5WKKN7t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbydWkK%2FdJMcadNXpwn%2FJkUGwFey3HiJhJ5WKKN7t0%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;1662&quot; height=&quot;1686&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바이너리 파일은 아래 경로에 위치&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;~/Library/Developer/Xcode/DerivedData/&amp;lt;Project&amp;gt;/Logs/Build/&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;얻어내는 법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode &amp;gt; Build &amp;gt; 오른쪽마우스 &amp;gt; Show in Finder 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRy13d/dJMcaioe73n/Mb4pyuqQi9LCF14EJlaE41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRy13d/dJMcaioe73n/Mb4pyuqQi9LCF14EJlaE41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRy13d/dJMcaioe73n/Mb4pyuqQi9LCF14EJlaE41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRy13d%2FdJMcaioe73n%2FMb4pyuqQi9LCF14EJlaE41%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;572&quot; height=&quot;544&quot; data-origin-width=&quot;572&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Show in Finder 클릭 시 Logs/Launch에 들어가게됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bM3iOX/dJMcai9zwgR/LHFoC8ujVfspPIL3xeYiF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bM3iOX/dJMcai9zwgR/LHFoC8ujVfspPIL3xeYiF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bM3iOX/dJMcai9zwgR/LHFoC8ujVfspPIL3xeYiF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbM3iOX%2FdJMcai9zwgR%2FLHFoC8ujVfspPIL3xeYiF0%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;1738&quot; height=&quot;924&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 Logs/Launch가 아닌, Logs/Build 경로에 가야하므로 Logs경로로 이동한 다음 Build 폴더로 이동
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마침내 UUID.xcactivitylog 파일 획득이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;928&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YxgYC/dJMcabvTnWx/lplEzru16iZLpy6j6QGmLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YxgYC/dJMcabvTnWx/lplEzru16iZLpy6j6QGmLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YxgYC/dJMcabvTnWx/lplEzru16iZLpy6j6QGmLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYxgYC%2FdJMcabvTnWx%2FlplEzru16iZLpy6j6QGmLk%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;1748&quot; height=&quot;928&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;928&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;들어있는 정보들&lt;br /&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 data-end=&quot;420&quot; data-start=&quot;399&quot;&gt;각 빌드 단계별 duration&lt;/li&gt;
&lt;li data-end=&quot;443&quot; data-start=&quot;421&quot;&gt;컴파일러가 어떤 파일을 빌드했는지&lt;/li&gt;
&lt;li data-end=&quot;466&quot; data-start=&quot;444&quot;&gt;Warning, Error 메시지&lt;/li&gt;
&lt;li data-end=&quot;522&quot; data-start=&quot;467&quot;&gt;SwiftCompile, Link, Run Script, Previews 등 모든 빌드 스텝&lt;/li&gt;
&lt;li data-end=&quot;542&quot; data-start=&quot;523&quot;&gt;Bitcode/LLVM 단계&lt;/li&gt;
&lt;li data-end=&quot;542&quot; data-start=&quot;523&quot;&gt;인덱싱(indexing) 관련 시간&lt;/li&gt;
&lt;li data-end=&quot;581&quot; data-start=&quot;567&quot;&gt;Test 실행 로그&lt;/li&gt;
&lt;li data-end=&quot;581&quot; data-start=&quot;567&quot;&gt;증분 빌드 캐시 사용 여부&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;xcactivitylog 파일 json 형태로 뽑아보기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;XCLogParser를 사용하여 json으로 뽑기가 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1764478601693&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install xclogparser&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;xcactivity 파일의 경로를 얻어오기위해 오른쪽 클릭 &amp;gt; &quot;정보 가져오기&quot; 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HCNfO/dJMcaaDKjIA/YuUqjJV0YYkQPzIywvz10K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HCNfO/dJMcaaDKjIA/YuUqjJV0YYkQPzIywvz10K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HCNfO/dJMcaaDKjIA/YuUqjJV0YYkQPzIywvz10K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHCNfO%2FdJMcaaDKjIA%2FYuUqjJV0YYkQPzIywvz10K%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;1268&quot; height=&quot;924&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위치 &amp;gt; path를 복사
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;path를 복사한 다음 파일 이름도 복사&lt;br /&gt;`/Users/jake/Library/Developer/Xcode/DerivedData/Performance1-frzqzmwaccvbjdfswawhmgkwahke/Logs/Build/51597595-B89A-4E8E-BC1C-842C12F78CD8.xcactivitylog`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;692&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3WAjE/dJMcadHcj0q/7Xik5IsAFBsLt5bkCAK4kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3WAjE/dJMcadHcj0q/7Xik5IsAFBsLt5bkCAK4kK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3WAjE/dJMcadHcj0q/7Xik5IsAFBsLt5bkCAK4kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3WAjE%2FdJMcadHcj0q%2F7Xik5IsAFBsLt5bkCAK4kK%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;524&quot; height=&quot;692&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;692&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 명령어를 통해 json형태로 추출 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1764478773740&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;xclogparser parse --project Your.xcactivitylog --output output.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1764479162963&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;xclogparser dump --file /Users/jake/Library/Developer/Xcode/DerivedData/Performance1-frzqzmwaccvbjdfswawhmgkwahke/Logs/Build/51597595-B89A-4E8E-BC1C-842C12F78CD8.xcactivitylog --output activity.json&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;생성된 activity.json을 열어보면 약 2000줄의 json 데이트 획득 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E5z1y/dJMcaaDKjOm/NsADY8FQRUTE5qemsxKkd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E5z1y/dJMcaaDKjOm/NsADY8FQRUTE5qemsxKkd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E5z1y/dJMcaaDKjOm/NsADY8FQRUTE5qemsxKkd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE5z1y%2FdJMcaaDKjOm%2FNsADY8FQRUTE5qemsxKkd1%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;1586&quot; height=&quot;1306&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* XCLogParser git: &lt;a href=&quot;https://github.com/MobileNativeFoundation/XCLogParser&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/MobileNativeFoundation/XCLogParser&lt;/a&gt;&lt;/p&gt;</description>
      <category>최적화하기</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>xclogparser</category>
      <category>빌드 로그</category>
      <category>최적화하기</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1827</guid>
      <comments>https://ios-development.tistory.com/1827#entry1827comment</comments>
      <pubDate>Wed, 3 Dec 2025 01:42:41 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] Instrument 결과물 trace파일 분석, xml 파일로 추출 방법 (xctrace export)</title>
      <link>https://ios-development.tistory.com/1826</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;.trace 파일&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Instruments를 통해 나오는 .trace 파일은&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자주쓰는 xctrace export 옵션&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1681&quot; data-start=&quot;1664&quot;&gt;--list
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1681&quot; data-start=&quot;1664&quot;&gt;trace 파일 내부에 어떤 데이터들이 들어있는지 전체 목록을 보여줌 (schema 이름들을 확인이 가능)&lt;/li&gt;
&lt;li data-end=&quot;1681&quot; data-start=&quot;1664&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;xctrace &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; --input test1.trace --list&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;예)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1830&quot; data-start=&quot;1815&quot;&gt;time-sample&lt;/li&gt;
&lt;li data-end=&quot;1843&quot; data-start=&quot;1831&quot;&gt;signpost&lt;/li&gt;
&lt;li data-end=&quot;1855&quot; data-start=&quot;1844&quot;&gt;process&lt;/li&gt;
&lt;li data-end=&quot;1872&quot; data-start=&quot;1856&quot;&gt;thread-state&lt;/li&gt;
&lt;li data-end=&quot;1889&quot; data-start=&quot;1873&quot;&gt;system-calls&lt;/li&gt;
&lt;li data-end=&quot;1900&quot; data-start=&quot;1890&quot;&gt;memory&lt;/li&gt;
&lt;li data-end=&quot;1914&quot; data-start=&quot;1901&quot;&gt;call-tree&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1966&quot; data-start=&quot;1950&quot;&gt;&amp;nbsp;--toc
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1966&quot; data-start=&quot;1950&quot;&gt;Trace Table of Contents(Toc)를 XML로 바로 출력&lt;/li&gt;
&lt;li data-end=&quot;1966&quot; data-start=&quot;1950&quot;&gt;xctrace &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; --input test1.trace --toc &lt;/span&gt;이걸 보면 전체 구조를 한눈에 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2111&quot; data-start=&quot;2093&quot;&gt;&amp;nbsp;--xpath
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2111&quot; data-start=&quot;2093&quot;&gt;특정 부분만 필터링하기 위한 고급 옵션&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;ex)&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2244&quot; data-start=&quot;2225&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2244&quot; data-start=&quot;2225&quot;&gt;signpost 데이터만 추출: --xpath &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;'//table[@schema=&quot;point-of-interest&quot;]'&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2244&quot; data-start=&quot;2225&quot;&gt;특정 이벤트 이름 필터: --xpath &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;'//event[@name=&quot;MyCustomSignpost&quot;]'&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;letter-spacing: normal;&quot;&gt;Insturments의 time profiler에서 데이터 추출해보기&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Insturments 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode 오픈 &amp;gt; cmd + I&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Instruments의 time profiler 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;1008&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qp4DF/dJMcachdKep/sMxILWjEsY4QoAOpy1MNOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qp4DF/dJMcachdKep/sMxILWjEsY4QoAOpy1MNOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qp4DF/dJMcachdKep/sMxILWjEsY4QoAOpy1MNOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqp4DF%2FdJMcachdKep%2FsMxILWjEsY4QoAOpy1MNOk%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;1604&quot; height=&quot;1008&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;1008&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좌측상단 녹화 버튼을 눌러서 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eu6aTk/dJMcafE1b3c/g8vAIBD1fRdSJSwdTcgqh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eu6aTk/dJMcafE1b3c/g8vAIBD1fRdSJSwdTcgqh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eu6aTk/dJMcafE1b3c/g8vAIBD1fRdSJSwdTcgqh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feu6aTk%2FdJMcafE1b3c%2Fg8vAIBD1fRdSJSwdTcgqh0%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;1594&quot; height=&quot;1034&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확인하고 싶은 부분을 테스트 폰에서 실행해본 후, instruments에서 중지 버튼 클릭 &amp;gt; instruments를 닫으면 test1으로 저장&lt;/li&gt;
&lt;li&gt;이 test1을 가지고 &lt;b&gt;time sample&lt;/b&gt;을 뽑아보기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;* &lt;b&gt;time-sample&lt;/b&gt;: Time Profiler가 일정 간격으로 CPU 스택을 찍어서 만든 &quot;Raw Samples&quot; 데이터&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1763875586665&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Time Profiler에서 수집된 &quot;raw CPU 샘플(time-sample)&quot; 데이터만 .trace 파일에서 추출해 XML로 저장하는 명령어
xctrace export --input test1.trace --xpath '/trace-toc/run/data/table[@schema=&quot;time-sample&quot;]' --output time-sample.xml&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;추출된 time-sample.xml을 실행시켜보면 정보가 등장
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;time sample 말 그대로, 시간별로 뽑은 것들의 결과값이 나옴&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1763875927236&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;trace-query-result&amp;gt;
&amp;lt;node xpath='//trace-toc[1]/run[1]/data[1]/table[3]'&amp;gt;&amp;lt;schema name=&quot;time-sample&quot;&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;time&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Timestamp&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;sample-time&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;thread&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Thread&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;thread&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;core-index&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Core Index&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;core&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;thread-state&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Thread State&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;thread-state&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;cp-kernel-callstack&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Kernel Callstack ID&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;kperf-bt&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;cp-user-callstack&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;User Callstack ID&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;kperf-bt&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;col&amp;gt;&amp;lt;mnemonic&amp;gt;sample-type&amp;lt;/mnemonic&amp;gt;&amp;lt;name&amp;gt;Sample type&amp;lt;/name&amp;gt;&amp;lt;engineering-type&amp;gt;time-sample-kind&amp;lt;/engineering-type&amp;gt;&amp;lt;/col&amp;gt;&amp;lt;/schema&amp;gt;&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;1&quot; fmt=&quot;00:00.372.885&quot;&amp;gt;372885208&amp;lt;/sample-time&amp;gt;&amp;lt;thread id=&quot;2&quot; fmt=&quot;Main Thread 0xc229 (Performance1, pid: 2875)&quot;&amp;gt;&amp;lt;tid id=&quot;3&quot; fmt=&quot;0xc229&quot;&amp;gt;49705&amp;lt;/tid&amp;gt;&amp;lt;process id=&quot;4&quot; fmt=&quot;Performance1 (2875)&quot;&amp;gt;&amp;lt;pid id=&quot;5&quot; fmt=&quot;2875&quot;&amp;gt;2875&amp;lt;/pid&amp;gt;&amp;lt;device-session id=&quot;6&quot; fmt=&quot;TODO&quot;&amp;gt;TODO&amp;lt;/device-session&amp;gt;&amp;lt;/process&amp;gt;&amp;lt;/thread&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;thread-state id=&quot;7&quot; fmt=&quot;Blocked&quot;&amp;gt;Blocked&amp;lt;/thread-state&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;8&quot; fmt=&quot;PC:0x1052f47c0, 1 frames, 0 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;9&quot; fmt=&quot;frag 799&quot;&amp;gt;4381951936&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address id=&quot;10&quot; fmt=&quot;0x1052f47c0&quot;&amp;gt;4381951936&amp;lt;/text-address&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind id=&quot;11&quot; fmt=&quot;Stackshot&quot;&amp;gt;3&amp;lt;/time-sample-kind&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time ref=&quot;1&quot;/&amp;gt;&amp;lt;thread ref=&quot;2&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;thread-state ref=&quot;7&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;8&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;11&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;12&quot; fmt=&quot;00:00.413.780&quot;&amp;gt;413780375&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;2&quot;/&amp;gt;&amp;lt;core id=&quot;13&quot; fmt=&quot;CPU 5&quot;&amp;gt;5&amp;lt;/core&amp;gt;&amp;lt;thread-state id=&quot;14&quot; fmt=&quot;Running&quot;&amp;gt;Running&amp;lt;/thread-state&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;15&quot; fmt=&quot;PC:0x1052f2c04, 19 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;16&quot; fmt=&quot;frag 5329&quot;&amp;gt;4378756604 4378696628 4378654252 4378651164 4378618192 4378650264 4378652064 4378683412 4378831396 4378824096 4378830696 4378682744 4378597104 4378596164 4381968536 4381963076 4381962712 4381961036 0&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address id=&quot;17&quot; fmt=&quot;0x1052f2c04&quot;&amp;gt;4381944836&amp;lt;/text-address&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content id=&quot;18&quot; fmt=&quot;0x104ff4044&quot;&amp;gt;4378804292&amp;lt;/register-content&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind id=&quot;19&quot; fmt=&quot;Timer Fired&quot;&amp;gt;0&amp;lt;/time-sample-kind&amp;gt;&amp;lt;/row&amp;gt;
...
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2409&quot; fmt=&quot;00:03.943.780&quot;&amp;gt;3943780041&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;240&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;1926&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2410&quot; fmt=&quot;00:03.944.778&quot;&amp;gt;3944778916&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;240&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;2139&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2411&quot; fmt=&quot;00:03.945.780&quot;&amp;gt;3945780458&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;323&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;1926&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2412&quot; fmt=&quot;00:03.947.779&quot;&amp;gt;3947779250&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;13&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2413&quot; fmt=&quot;PC:0x1970593f4, 11 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses ref=&quot;921&quot;/&amp;gt;&amp;lt;text-address ref=&quot;2146&quot;/&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content ref=&quot;2147&quot;/&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2414&quot; fmt=&quot;00:03.948.779&quot;&amp;gt;3948779458&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;13&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2415&quot; fmt=&quot;PC:0x1970583a8, 16 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses ref=&quot;2387&quot;/&amp;gt;&amp;lt;text-address ref=&quot;391&quot;/&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content ref=&quot;387&quot;/&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2416&quot; fmt=&quot;00:03.949.779&quot;&amp;gt;3949779958&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;240&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2417&quot; fmt=&quot;PC:0x197059278, 34 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;2418&quot; fmt=&quot;frag 6876&quot;&amp;gt;6828688312 6828680388 6828336324 6828673252 6828665960 6828688100 6828679012 7578375508 7578378520 7578379392 7578375240 7578374900 7578283052 7578280924 7578378536 7578379392 7578375240 7578374900 7578283052 7578280924 7578378536 7578379392 7578375240 7578374900 7578283052 7578280924 7578378536 7578385764 6444364976 6444476452 6444334424 6444336400 4377979792 4377975180&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address ref=&quot;951&quot;/&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content ref=&quot;387&quot;/&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2419&quot; fmt=&quot;00:07.247.782&quot;&amp;gt;7247782291&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;2&quot;/&amp;gt;&amp;lt;core ref=&quot;447&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2420&quot; fmt=&quot;PC:0x1051c4b70, 34 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;2421&quot; fmt=&quot;frag 8147&quot;&amp;gt;4380740648 4380708568 6443621400 6443619872 6443619304 6443366520 6444364976 6444276492 6444276100 6443364636 6443433384 6443431928 6443422148 6443435012 6543765396 6444364976 6444276492 6576072508 6576068460 6446961884 6446961700 6446959536 6446955908 6446935588 6749886908 6545603644 6545620580 7934333500 7934332804 7931750860 4377788496 4378596304 4381961112 0&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address ref=&quot;381&quot;/&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content ref=&quot;382&quot;/&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2422&quot; fmt=&quot;00:28.042.779&quot;&amp;gt;28042779958&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;2&quot;/&amp;gt;&amp;lt;core ref=&quot;13&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2423&quot; fmt=&quot;PC:0x1800aef68, 21 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;2424&quot; fmt=&quot;frag 9467&quot;&amp;gt;6448065688 6447321988 6495968380 6444321556 6444364976 6444479648 6444319516 6444318316 6446960656 6446957032 6446935588 6749886908 6545603644 6545620580 7934333500 7934332804 7931750860 4377788496 4378596304 4381961112 0&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address id=&quot;2425&quot; fmt=&quot;0x1800aef68&quot;&amp;gt;6443167592&amp;lt;/text-address&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content id=&quot;2426&quot; fmt=&quot;0x180091e14&quot;&amp;gt;6443048468&amp;lt;/register-content&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2427&quot; fmt=&quot;00:50.779.780&quot;&amp;gt;50779780083&amp;lt;/sample-time&amp;gt;&amp;lt;thread id=&quot;2428&quot; fmt=&quot;Performance1 0xcbd4 (Performance1, pid: 2875)&quot;&amp;gt;&amp;lt;tid id=&quot;2429&quot; fmt=&quot;0xcbd4&quot;&amp;gt;52180&amp;lt;/tid&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;/thread&amp;gt;&amp;lt;core ref=&quot;240&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;419&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2430&quot; fmt=&quot;00:58.435.779&quot;&amp;gt;58435779958&amp;lt;/sample-time&amp;gt;&amp;lt;thread id=&quot;2431&quot; fmt=&quot;Performance1 0xcd65 (Performance1, pid: 2875)&quot;&amp;gt;&amp;lt;tid id=&quot;2432&quot; fmt=&quot;0xcd65&quot;&amp;gt;52581&amp;lt;/tid&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;/thread&amp;gt;&amp;lt;core ref=&quot;126&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt id=&quot;2433&quot; fmt=&quot;PC:0x104f8876c, 12 frames, 1 regs, pid: 2875&quot;&amp;gt;&amp;lt;text-addresses id=&quot;2434&quot; fmt=&quot;frag 10618&quot;&amp;gt;6446876424 6446876264 6448042820 6448062604 6444255144 6444364976 6444293160 6444295912 6444340532 6444338292 4377979852 4377975180&amp;lt;/text-addresses&amp;gt;&amp;lt;text-address ref=&quot;687&quot;/&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;register-content id=&quot;2435&quot; fmt=&quot;0x104f2916c&quot;&amp;gt;4377973100&amp;lt;/register-content&amp;gt;&amp;lt;/kperf-bt&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2436&quot; fmt=&quot;02:17.107.781&quot;&amp;gt;137107781291&amp;lt;/sample-time&amp;gt;&amp;lt;thread id=&quot;2437&quot; fmt=&quot;Performance1 0xd37a (Performance1, pid: 2875)&quot;&amp;gt;&amp;lt;tid id=&quot;2438&quot; fmt=&quot;0xd37a&quot;&amp;gt;54138&amp;lt;/tid&amp;gt;&amp;lt;process ref=&quot;4&quot;/&amp;gt;&amp;lt;/thread&amp;gt;&amp;lt;core ref=&quot;126&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;419&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;
&amp;lt;/node&amp;gt;&amp;lt;/trace-query-result&amp;gt;&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;row 하나 해석해보기&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;kberf-bt가 중요한 데이터&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1763876060384&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;row&amp;gt;&amp;lt;sample-time id=&quot;2410&quot; fmt=&quot;00:03.944.778&quot;&amp;gt;3944778916&amp;lt;/sample-time&amp;gt;&amp;lt;thread ref=&quot;509&quot;/&amp;gt;&amp;lt;core ref=&quot;240&quot;/&amp;gt;&amp;lt;thread-state ref=&quot;14&quot;/&amp;gt;&amp;lt;sentinel/&amp;gt;&amp;lt;kperf-bt ref=&quot;2139&quot;/&amp;gt;&amp;lt;time-sample-kind ref=&quot;19&quot;/&amp;gt;&amp;lt;/row&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;3263&quot; data-start=&quot;3049&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;3263&quot; data-start=&quot;3077&quot;&gt;
&lt;tr data-end=&quot;3112&quot; data-start=&quot;3077&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3091&quot; data-start=&quot;3077&quot;&gt;sample-time&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3112&quot; data-start=&quot;3091&quot;&gt;3.944초 지점에서 찍힌 샘플&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3142&quot; data-start=&quot;3113&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3122&quot; data-start=&quot;3113&quot;&gt;thread&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3142&quot; data-start=&quot;3122&quot;&gt;thread 509가 실행 중&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3172&quot; data-start=&quot;3143&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3150&quot; data-start=&quot;3143&quot;&gt;core&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3172&quot; data-start=&quot;3150&quot;&gt;CPU 코어 4 (ref=240)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3199&quot; data-start=&quot;3173&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3188&quot; data-start=&quot;3173&quot;&gt;thread-state&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3199&quot; data-start=&quot;3188&quot;&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3233&quot; data-start=&quot;3200&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3211&quot; data-start=&quot;3200&quot;&gt;kperf-bt&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3233&quot; data-start=&quot;3211&quot;&gt;&lt;u&gt;&lt;b&gt;이 순간의 콜스택 (핵심 데이터)&lt;/b&gt;&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3263&quot; data-start=&quot;3234&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3248&quot; data-start=&quot;3234&quot;&gt;sample-kind&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;3263&quot; data-start=&quot;3248&quot;&gt;Timer Fired&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉)&lt;/p&gt;
&lt;pre id=&quot;code_1763876578197&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;앱이 실행된 지 약 3.944초가 지났을 때(Time Profiler 샘플링 순간),
스레드 509(아마 Main Thread 또는 Worker Thread)가
CPU 4번 코어에서 Running 상태였고,
그 시점의 콜스택은 Backtrace ID 2139에 기록됐다.
이 샘플은 Timer Fired 이벤트로 찍혔다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;time-sample 데이터를 읽어서, 같은 Backtrace(kperf-bt ID) 또는 같은 함수 주소(symbol)로 그룹화 &amp;rarr; 샘플 개수를 세면 &amp;rarr; 가장 많이 찍힌 함수 = 가장 오래 걸린 부분&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가장 많이 찍힌 함수가 왜 가장 오래걸렸는지 파악할 수 있는지?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Time Profiler는 함수가 &amp;ldquo;얼마나 오래 실행됐는지&amp;rdquo; 직접 측정하지 않음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;대신, &lt;b&gt;일정한 시간 간격(예: 1ms)에 한 번씩 CPU의 현재 스택을 찍기 때문에 카운트를 통해 오래걸렸는지 파악이 가능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>최적화하기</category>
      <category>Instrument</category>
      <category>instrument 결과물</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>trace 파일</category>
      <category>성능 최적화</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1826</guid>
      <comments>https://ios-development.tistory.com/1826#entry1826comment</comments>
      <pubDate>Wed, 26 Nov 2025 01:47:48 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 4. VScode 단축키 모음 (+깃헙 코파일럿)</title>
      <link>https://ios-development.tistory.com/1825</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 검색 관련&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 파일 탐색: cmd + P&lt;br /&gt;*&amp;nbsp;문자열&amp;nbsp;전체&amp;nbsp;탐색:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;F&lt;br /&gt;*&amp;nbsp;파일&amp;nbsp;내&amp;nbsp;검색:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;O&lt;br /&gt;*&amp;nbsp;다음/이전&amp;nbsp;검색&amp;nbsp;결과로&amp;nbsp;이동:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;G&amp;nbsp;/&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;G&lt;br /&gt;*&amp;nbsp;검색된&amp;nbsp;상태에서&amp;nbsp;아래로&amp;nbsp;내려가기:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;&amp;darr;&lt;br /&gt;*&amp;nbsp;현재파일에서&amp;nbsp;바꾸기:&amp;nbsp;opt&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;F&lt;br /&gt;*&amp;nbsp;전체파일에서&amp;nbsp;바꾸기:&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;H&lt;br /&gt;*&amp;nbsp;현재파일&amp;nbsp;심볼&amp;nbsp;이름&amp;nbsp;바꾸기:&amp;nbsp;F2&lt;br /&gt;* 해당 폴더 안에서 검색: option + shift + F&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp;포커싱/탐색&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 코파일럿 챗 오픈 &amp;amp; 포커싱: ctrl + cmd + i&lt;br /&gt;*&amp;nbsp;코파일럿&amp;nbsp;챗&amp;nbsp;클로즈&amp;nbsp;/&amp;nbsp;오픈:&amp;nbsp;option&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;B&lt;br /&gt;*&amp;nbsp;코파일럿&amp;nbsp;챗&amp;nbsp;agent&amp;nbsp;/&amp;nbsp;ask&amp;nbsp;모드&amp;nbsp;선택:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;.&lt;br /&gt;*&amp;nbsp;커밋&amp;nbsp;그래프로&amp;nbsp;포커싱:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;G&lt;br /&gt;*&amp;nbsp;현재&amp;nbsp;파일로&amp;nbsp;Explorer&amp;nbsp;포커싱:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;E&lt;br /&gt;*&amp;nbsp;탐색기에서&amp;nbsp;파일&amp;nbsp;포커싱:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;&amp;darr;&lt;br /&gt;*&amp;nbsp;이전/다음&amp;nbsp;위치로&amp;nbsp;커서&amp;nbsp;이동:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;-&lt;br /&gt;*&amp;nbsp;다음&amp;nbsp;라인으로&amp;nbsp;커서&amp;nbsp;이동:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;enter&lt;br /&gt;*&amp;nbsp;소스&amp;nbsp;편집기로&amp;nbsp;바로&amp;nbsp;포커싱:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;1~9&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 창/탭&amp;nbsp;이동&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 탭 닫기: cmd + W&lt;br /&gt;*&amp;nbsp;탭&amp;nbsp;다&amp;nbsp;닫기:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;K&amp;nbsp;누른&amp;nbsp;후&amp;nbsp;W&lt;br /&gt;*&amp;nbsp;닫은&amp;nbsp;탭&amp;nbsp;다시&amp;nbsp;열기:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;T&lt;br /&gt;*&amp;nbsp;창분할:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;\&lt;br /&gt;*&amp;nbsp;창이동:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;1~9&lt;br /&gt;*&amp;nbsp;탭이동:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;1~9&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4.&amp;nbsp;기타&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 터미널 열기/닫기: cmd + J&lt;br /&gt;*&amp;nbsp;정의된&amp;nbsp;부분으로&amp;nbsp;점프:&amp;nbsp;F12&amp;nbsp;또는&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;클릭&lt;br /&gt;*&amp;nbsp;빌드:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;B&lt;br /&gt;*&amp;nbsp;라인이동:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;g&lt;br /&gt;*&amp;nbsp;커밋&amp;nbsp;그래프로&amp;nbsp;이동:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;G&lt;br /&gt;*&amp;nbsp;휠&amp;nbsp;처럼&amp;nbsp;스크롤:&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;fn&amp;nbsp;+&amp;nbsp;page&amp;nbsp;up/down&lt;br /&gt;*&amp;nbsp;사이드바&amp;nbsp;숨기기/보기:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;B&lt;br /&gt;*&amp;nbsp;영역&amp;nbsp;접기/펴기:&amp;nbsp;opt&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;[&amp;nbsp;또는&amp;nbsp;opt&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;]&amp;nbsp;&amp;nbsp;*&amp;nbsp;영역&amp;nbsp;접기/펴기:&amp;nbsp;opt&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;[&amp;nbsp;or&amp;nbsp;]&lt;br /&gt;*&amp;nbsp;단축키창&amp;nbsp;열기:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;K&amp;nbsp;+&amp;nbsp;S&lt;br /&gt;*&amp;nbsp;워닝나는&amp;nbsp;곳&amp;nbsp;자동&amp;nbsp;수정:&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;.&lt;br /&gt;*&amp;nbsp;절대경로&amp;nbsp;복사:&amp;nbsp;폴더&amp;nbsp;클릭&amp;nbsp;+&amp;nbsp;option&amp;nbsp;+&amp;nbsp;cmd&amp;nbsp;+&amp;nbsp;C&lt;br /&gt;*&amp;nbsp;파이썬&amp;nbsp;실행&amp;nbsp;단축키&amp;nbsp;설정:&amp;nbsp;단축키창&amp;nbsp;오픈&amp;nbsp;&amp;gt;&amp;nbsp;run&amp;nbsp;python&amp;nbsp;file&amp;nbsp;검색&amp;nbsp;&amp;gt;&amp;nbsp;option&amp;nbsp;+&amp;nbsp;R&lt;br /&gt;*&amp;nbsp;코드&amp;nbsp;위로&amp;nbsp;or&amp;nbsp;아래로&amp;nbsp;이동:&amp;nbsp;option&amp;nbsp;+&amp;nbsp;방향키&amp;nbsp;위아래&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 깃 그래프 열기: ctrl + shift + cmd + C (커스텀 -&amp;gt; cmd+K cmd+C -&amp;gt; git graph: View git ...) &amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 깃&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 커밋: 단축키창 오픈 &amp;gt; git commit 입력 &amp;gt; ctrl + shift + C&lt;br /&gt;*&amp;nbsp;푸시:&amp;nbsp;단축키창&amp;nbsp;오픈&amp;nbsp;&amp;gt;&amp;nbsp;git&amp;nbsp;push&amp;nbsp;입력&amp;nbsp;&amp;gt;&amp;nbsp;ctrl&amp;nbsp;+&amp;nbsp;shift&amp;nbsp;+&amp;nbsp;P&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. VScode 세팅&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VScode &amp;gt; cmd + shift + P &amp;gt; &quot;Open User Settings (JSON)&quot; 클릭&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;setting.json 파일이 열리는데, 이 파일은 VScode를 사용할때, preference 설정을 json의 key-value객체로 저장하여 이것만 복붙해서 사용하면, 환경이 변경되어도 동일하게 사용가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;swift&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;{
    &quot;workbench.colorTheme&quot;: &quot;Atom One Light&quot;,
    &quot;github.copilot.nextEditSuggestions.enabled&quot;: true,
    &quot;makefile.configureOnOpen&quot;: true,
    &quot;files.autoSave&quot;: &quot;afterDelay&quot;,
    &quot;workbench.editor.showTabs&quot;: &quot;single&quot;,
    &quot;editor.minimap.enabled&quot;: false,
    &quot;editor.wordWrap&quot;: &quot;on&quot;,
    &quot;python.defaultInterpreterPath&quot;: &quot;/usr/local/bin/python3&quot;,
    &quot;explorer.confirmDelete&quot;: false,
    &quot;containers.containerClient&quot;: &quot;com.microsoft.visualstudio.containers.docker&quot;,
    &quot;containers.orchestratorClient&quot;: &quot;com.microsoft.visualstudio.orchestrators.dockercompose&quot;,
    &quot;git.enableSmartCommit&quot;: true,
    &quot;git.useEditorAsCommitInput&quot;: false,
    &quot;claudeCode.preferredLocation&quot;: &quot;panel&quot;,
    &quot;claudeCode.selectedModel&quot;: &quot;default&quot;,
    &quot;chat.viewSessions.enabled&quot;: false,
    &quot;editor.find.seedSearchStringFromSelection&quot;: &quot;never&quot;,
    &quot;claudeCode.allowDangerouslySkipPermissions&quot;: true,
    &quot;chat.tools.global.autoApprove&quot;: true
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>vscode</category>
      <category>vscode 단축키</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1825</guid>
      <comments>https://ios-development.tistory.com/1825#entry1825comment</comments>
      <pubDate>Wed, 19 Nov 2025 01:51:55 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 3. VScode에 깃헙 코파일럿 활용 방법 (github copilot, 지침, 프롬프트, instruction, prompt)</title>
      <link>https://ios-development.tistory.com/1824</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;목차&amp;gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://ios-development.tistory.com/1822&quot;&gt;VScode에 깃헙 코파일럿 세팅 방법 (github&amp;nbsp;copilot)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://ios-development.tistory.com/1823&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VScode에 깃헙 코파일럿 활용 방법 (github&amp;nbsp;copilot,&amp;nbsp;Ask,&amp;nbsp;Agent,&amp;nbsp;Edit)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;VScode에 깃헙 코파일럿 활용 방법 (github copilot, 지침, 프롬프트)&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;지침 (Instruction)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;695&quot; data-start=&quot;587&quot;&gt;&amp;ldquo;사전 정의된 규칙&amp;rdquo;이나 &amp;ldquo;코딩 컨벤션&amp;rdquo;, &amp;ldquo;프로젝트의 스타일 가이드&amp;rdquo; 등의 형태로 Copilot에게 알려줄 수 있는 정보&lt;span data-state=&quot;closed&quot;&gt;&lt;span data-testid=&quot;webpage-citation-pill&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2511&quot; data-start=&quot;2368&quot;&gt;ex) &amp;ldquo;모든 파일은 더블 쿼트(&amp;ldquo;&amp;rdquo;)를 사용하고, 탭으로 들여쓰기 한다&amp;rdquo;는 지침을 설정해두고, 나중에 프롬프트로 &amp;ldquo;이 함수 리팩토링해주세요&amp;rdquo; 했을 때 Copilot이 자동으로 해당 스타일을 반영해서 코드를 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;2511&quot; data-start=&quot;2368&quot;&gt;적용하려는 폴더에 .github/copilot-instructions.md 파일을 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2511&quot; data-start=&quot;2368&quot;&gt;파일 이름은 &quot;instructions.md&quot;로만 끝나면 알아서 찾아서 해줌&lt;/li&gt;
&lt;li data-end=&quot;2511&quot; data-start=&quot;2368&quot;&gt;여기에 지침을 적어서 AI에게 알려주는 형태&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지침 적용 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 루트에서 .github 폴더 생성 후 여기에 instructions.md 형태의 이름으로 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjnARB/dJMcabbqcQe/K4matJiwAemKUPuMiX3DI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjnARB/dJMcabbqcQe/K4matJiwAemKUPuMiX3DI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjnARB/dJMcabbqcQe/K4matJiwAemKUPuMiX3DI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjnARB%2FdJMcabbqcQe%2FK4matJiwAemKUPuMiX3DI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;301&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;764&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FI7GT/dJMcae63rJ7/yHHK8uJvuWWvChPukwQKw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FI7GT/dJMcae63rJ7/yHHK8uJvuWWvChPukwQKw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FI7GT/dJMcae63rJ7/yHHK8uJvuWWvChPukwQKw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFI7GT%2FdJMcae63rJ7%2FyHHK8uJvuWWvChPukwQKw1%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;774&quot; height=&quot;764&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;764&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지침 적용하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;챗에 커서를 두고 `cmd + /` 단축키 &amp;gt; 지침 이름을 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daHv7t/dJMcae63rJZ/wWNzTM9BUlR2CqAJueZphk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daHv7t/dJMcae63rJZ/wWNzTM9BUlR2CqAJueZphk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daHv7t/dJMcae63rJZ/wWNzTM9BUlR2CqAJueZphk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaHv7t%2FdJMcae63rJZ%2FwWNzTM9BUlR2CqAJueZphk%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;1366&quot; height=&quot;214&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;챗을 확인해보면 my-instructions.md가 들어가있음&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 여기에 어떤 요청을 하면 이 지침을 따라서 적용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clpunU/dJMb99Lrw6h/xvy1MX74uOrNvSOLJo1Zh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clpunU/dJMb99Lrw6h/xvy1MX74uOrNvSOLJo1Zh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clpunU/dJMb99Lrw6h/xvy1MX74uOrNvSOLJo1Zh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclpunU%2FdJMb99Lrw6h%2Fxvy1MX74uOrNvSOLJo1Zh0%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;274&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프롬프트 (prompt)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마크다운 형식으로 작성된 재사용 가능한 프롬프트 템플릿
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 개발자가 자주 사용하는 프롬프트(예: 코드 생성 지시, 리팩토링 요청, 리뷰 요청 등)를 미리 정의해 놓고 필요할 때 꺼내 써서 일관된 형태로 GitHub Copilot에게 요청할 수 있게 해주는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;프롬프트 사용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;./github/my-prompt.md 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt0j77/dJMcabJf9qt/WcGij9xJ1BGSiPGJJw9rW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt0j77/dJMcabJf9qt/WcGij9xJ1BGSiPGJJw9rW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt0j77/dJMcabJf9qt/WcGij9xJ1BGSiPGJJw9rW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt0j77%2FdJMcabJf9qt%2FWcGij9xJ1BGSiPGJJw9rW1%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;545&quot; height=&quot;479&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같이 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762058129950&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;my-prompt.md

[상황]
현재 이 ViewModel은 completion handler 기반으로 네트워크 요청을 수행합니다.
async/await 문법으로 바꾸고 싶습니다.

[명령]
fetchData() 함수를 async/await 구조로 리팩토링해주세요.

[조건]
에러 처리는 Result 타입 대신 do-catch로 해주세요.
Swift 5.9 문법 사용.

[출력]
주석 포함한 코드로 보여주세요.&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;이 프롬프트를 수행하고 싶은 경우, 지침과 동일하게 채팅 &amp;gt; `cmd + /` 누르고 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dr5c1u/dJMcahvWmoD/fi3dJyBPcDHgBNs3I0FAP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dr5c1u/dJMcahvWmoD/fi3dJyBPcDHgBNs3I0FAP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dr5c1u/dJMcahvWmoD/fi3dJyBPcDHgBNs3I0FAP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdr5c1u%2FdJMcahvWmoD%2Ffi3dJyBPcDHgBNs3I0FAP1%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;1274&quot; height=&quot;280&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ScnMP/dJMcahCHZVV/GbUt82a1DxFCwjuotlhW21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ScnMP/dJMcahCHZVV/GbUt82a1DxFCwjuotlhW21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ScnMP/dJMcahCHZVV/GbUt82a1DxFCwjuotlhW21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FScnMP%2FdJMcahCHZVV%2FGbUt82a1DxFCwjuotlhW21%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;620&quot; height=&quot;214&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기에 챗으로 요청하면 프롬프트에 내용에 맞게 답변을하거나 코드를 작성해줌&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전역적으로 지침 적용하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 알아본건 `cmd + /`하여 지침을 따로 선택해야했지만, settings.json 파일을 만들어서 여기에 따로 선택 안하고 적용되도록 할 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;루트 경로에 .github/settings.json 파일 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;1036&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cP9mBP/dJMcahvWmoW/P8iVKOUXnQoKqWVGjCGBR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cP9mBP/dJMcahvWmoW/P8iVKOUXnQoKqWVGjCGBR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cP9mBP/dJMcahvWmoW/P8iVKOUXnQoKqWVGjCGBR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcP9mBP%2FdJMcahvWmoW%2FP8iVKOUXnQoKqWVGjCGBR1%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;726&quot; height=&quot;1036&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;1036&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`github.copilot.chat.codeGeneration.instructions`를 키값으로하고, 배열로 text에 넣어주면 됨&lt;/li&gt;
&lt;li&gt;이렇게하면 별도로 지침을 선택하면서 매번 적용하지 않아도됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762058869803&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;github.copilot.chat.codeGeneration.instructions&quot;: [
    {
      &quot;text&quot;: &quot;모든 코드는 한글로 주석을 작성해줘&quot;
    }
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://docs.github.com/ko/copilot/how-tos/configure-custom-instructions/add-repository-instructions&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.github.com/ko/copilot/how-tos/configure-custom-instructions/add-repository-instructions&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://copilot-instructions.md/?utm_source=chatgpt.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://copilot-instructions.md/?utm_source=chatgpt.com&lt;/a&gt;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>GitHub Copilot</category>
      <category>instruction</category>
      <category>ios</category>
      <category>prompt</category>
      <category>swiftr</category>
      <category>깃헙 코파일럿</category>
      <category>지침</category>
      <category>프롬프트</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1824</guid>
      <comments>https://ios-development.tistory.com/1824#entry1824comment</comments>
      <pubDate>Wed, 12 Nov 2025 01:11:41 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 2. VScode로 깃헙 코파일럿 기능 활용 방법 (github copilot, Ask, Agent, Edit)</title>
      <link>https://ios-development.tistory.com/1823</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;목차&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;a href=&quot;https://ios-development.tistory.com/1822&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VScode에 깃헙 코파일럿 세팅 방법 (github&amp;nbsp;copilot)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;VScode에 깃헙 코파일럿 활용 방법 (github&amp;nbsp;copilot,&amp;nbsp;Ask,&amp;nbsp;Agent,&amp;nbsp;Edit)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;a href=&quot;https://ios-development.tistory.com/1824&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VScode에 깃헙 코파일럿 활용 방법 (github copilot, 지침, 프롬프트)&lt;/a&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;깃헙 코파일럿 기능 - context단위로 물어보기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 mongodb 폴더에 관해 궁금한 경우?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;1242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmMpaV/dJMb9MpnHNz/y8vB1xptjBXCaGhjtrKvj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmMpaV/dJMb9MpnHNz/y8vB1xptjBXCaGhjtrKvj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmMpaV/dJMb9MpnHNz/y8vB1xptjBXCaGhjtrKvj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmMpaV%2FdJMb9MpnHNz%2Fy8vB1xptjBXCaGhjtrKvj0%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;515&quot; height=&quot;796&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;1242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;폴더 오른쪽 마우스 클릭 &amp;gt; Add Folder to Chat 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjKNZ0/dJMb9LxfcBK/UxRvEmGGPPwKlb6kM2Y2n0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjKNZ0/dJMb9LxfcBK/UxRvEmGGPPwKlb6kM2Y2n0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjKNZ0/dJMb9LxfcBK/UxRvEmGGPPwKlb6kM2Y2n0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjKNZ0%2FdJMb9LxfcBK%2FUxRvEmGGPPwKlb6kM2Y2n0%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;1022&quot; height=&quot;916&quot; data-origin-width=&quot;1022&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그럼 채팅에 mongosh 폴더 context가 들어가고 질문하면 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEyAC6/dJMb9PTWEw8/dkCJlblyOjUmqHwoyQ0nRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEyAC6/dJMb9PTWEw8/dkCJlblyOjUmqHwoyQ0nRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEyAC6/dJMb9PTWEw8/dkCJlblyOjUmqHwoyQ0nRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEyAC6%2FdJMb9PTWEw8%2FdkCJlblyOjUmqHwoyQ0nRK%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;726&quot; height=&quot;396&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;코드 editor에서 수정요청 하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단축키 cmd + I 입력 &amp;gt; 인라인 채팅창이 보이면 여기에 필요한 요청을 적기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccW0fN/dJMb9P7tMFF/mhJqEvMOmQFzP175Z5Pjj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccW0fN/dJMb9P7tMFF/mhJqEvMOmQFzP175Z5Pjj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccW0fN/dJMb9P7tMFF/mhJqEvMOmQFzP175Z5Pjj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccW0fN%2FdJMb9P7tMFF%2FmhJqEvMOmQFzP175Z5Pjj0%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;1474&quot; height=&quot;720&quot; data-origin-width=&quot;1474&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초록색으로 AI가 응답해주고, Accept을 누르면 적용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5DuJ6/dJMb9Qk04r7/6KvBP7zn9vETSk5V6pnFZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5DuJ6/dJMb9Qk04r7/6KvBP7zn9vETSk5V6pnFZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5DuJ6/dJMb9Qk04r7/6KvBP7zn9vETSk5V6pnFZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5DuJ6%2FdJMb9Qk04r7%2F6KvBP7zn9vETSk5V6pnFZk%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;1400&quot; height=&quot;566&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;코드 적용하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;채팅에서 AI가 알려준 코드 부분에 마우스를 갖다대면 버튼들이 보여지는데, 이 버튼들은 코드에 적용시킬 수 있는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;1412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZnwjz/dJMcagDNJr5/DUXnxjT2P8QpB1hKkLXNA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZnwjz/dJMcagDNJr5/DUXnxjT2P8QpB1hKkLXNA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZnwjz/dJMcagDNJr5/DUXnxjT2P8QpB1hKkLXNA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZnwjz%2FdJMcagDNJr5%2FDUXnxjT2P8QpB1hKkLXNA0%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;392&quot; height=&quot;923&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;1412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 앞 두 가지 버튼은 유용하게 쓸 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;260&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/edrqDW/dJMcabCuurc/1tKjmdSXyxWbbtalDK3m60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/edrqDW/dJMcabCuurc/1tKjmdSXyxWbbtalDK3m60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/edrqDW/dJMcabCuurc/1tKjmdSXyxWbbtalDK3m60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FedrqDW%2FdJMcabCuurc%2F1tKjmdSXyxWbbtalDK3m60%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;260&quot; height=&quot;88&quot; data-origin-width=&quot;260&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫번째 버튼은 알아서 코드에 적용시켜달라는 것이고, 두번쨰 버튼은 코드부분에 있는 내 커서에 해당 코드를 적용시키라는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;채팅 타입 - Ask, Agent, Edit&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vscode &amp;gt; chat 부분에 Ask로 되어있는 부분을 선택하면 3가지 옵션이 존재&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Ask: &lt;b&gt;질문-답변형 지원&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;으로, 코드 변경 없이 &amp;ldquo;지식이나 설명이 필요할 때&amp;rdquo; 사용하기 좋음&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;260&quot; data-end=&quot;283&quot;&gt;&amp;ldquo;이 함수가 무슨 역할을 하나요?&amp;rdquo;&lt;/li&gt;
&lt;li data-start=&quot;286&quot; data-end=&quot;316&quot;&gt;&amp;ldquo;이 라이브러리에서 어떤 패턴을 써야 하나요?&amp;rdquo;&lt;/li&gt;
&lt;li data-start=&quot;319&quot; data-end=&quot;342&quot;&gt;&amp;ldquo;이 코드의 버그 원인은 뭘까요?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Edit: 코드 변경을 지시하고 직접 수정 제안을 받아보는 모드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;724&quot; data-start=&quot;687&quot;&gt;&amp;ldquo;이 함수에서 async/await 방식으로 바꿔 주세요.&amp;rdquo;&lt;/li&gt;
&lt;li data-end=&quot;749&quot; data-start=&quot;727&quot;&gt;&amp;ldquo;에러 핸들링을 추가해 주세요.&amp;rdquo;&lt;/li&gt;
&lt;li data-end=&quot;781&quot; data-start=&quot;752&quot;&gt;&amp;ldquo;이 파일들에 null 체크를 넣어 주세요.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Agent: 가장 강력하고 &amp;ldquo;AI에게 큰 작업을 위임&amp;rdquo;하는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;1185&quot; data-end=&quot;1221&quot;&gt;&amp;ldquo;이 앱에 인증 기능을 추가하고 테스트도 만들어 주세요.&amp;rdquo;&lt;/li&gt;
&lt;li data-start=&quot;1224&quot; data-end=&quot;1279&quot;&gt;&amp;ldquo;이 코드베이스 전체를 최신 스타일로 리팩토링하고, 빌드/테스트까지 자동으로 돌려 주세요.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Nov-02-2025 12-57-29.gif&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/stiYa/dJMcaiaxUcq/foGmMSruIFdViwymjpTQQk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/stiYa/dJMcaiaxUcq/foGmMSruIFdViwymjpTQQk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/stiYa/dJMcaiaxUcq/foGmMSruIFdViwymjpTQQk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/stiYa/dJMcaiaxUcq/foGmMSruIFdViwymjpTQQk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;356&quot; data-filename=&quot;Nov-02-2025 12-57-29.gif&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;모드&lt;/td&gt;
&lt;td&gt;사용 상황&lt;/td&gt;
&lt;td&gt;변경 가능성&lt;/td&gt;
&lt;td&gt;AI 기여&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask&lt;/td&gt;
&lt;td&gt;개념 설명, 코드 이해, 빠른 질문&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit&lt;/td&gt;
&lt;td&gt;특정 파일/구역에 대한 수정 지시&lt;/td&gt;
&lt;td&gt;있음&lt;/td&gt;
&lt;td&gt;중간 (사용자가 승인)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent&lt;/td&gt;
&lt;td&gt;프로젝트 전체 또는 다파일 작업 위임 (오래걸림)&lt;/td&gt;
&lt;td&gt;있음, 광범위한 변경 가능&lt;/td&gt;
&lt;td&gt;높음 (AI 주도, 사용자가 검토)&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2178&quot; data-start=&quot;2150&quot;&gt;사용 Tip
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2178&quot; data-start=&quot;2150&quot;&gt;&lt;b&gt;모르는 것이 있을 때&lt;/b&gt; &amp;rarr; Ask 모드&lt;/li&gt;
&lt;li data-end=&quot;2232&quot; data-start=&quot;2179&quot;&gt;&lt;b&gt;어떤 수정을 해야 할지 알고 있지만 직접 코딩은 피하고 싶을 때&lt;/b&gt; &amp;rarr; Edit 모드&lt;/li&gt;
&lt;li data-end=&quot;2284&quot; data-start=&quot;2233&quot;&gt;&lt;b&gt;큰 기능을 추가하거나 리팩토링/자동화 작업을 하고 싶을 때&lt;/b&gt; &amp;rarr; Agent 모드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>Agent</category>
      <category>ASK</category>
      <category>EDIT</category>
      <category>GitHub Copilot</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>깃헙 코파일럿</category>
      <category>코파일럿</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1823</guid>
      <comments>https://ios-development.tistory.com/1823#entry1823comment</comments>
      <pubDate>Wed, 5 Nov 2025 01:10:30 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 1.  VScode에 깃헙 코파일럿 세팅 방법 (github copilot)</title>
      <link>https://ios-development.tistory.com/1822</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;목차&amp;gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;b&gt;&amp;nbsp;VScode에 깃헙 코파일럿 세팅 방법&lt;span&gt;&amp;nbsp;&lt;/span&gt;(github&amp;nbsp;copilot)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;&lt;a style=&quot;color: #0070d1; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1823&quot;&gt;VScode에 깃헙 코파일럿 활용 방법&lt;span&gt;&amp;nbsp;&lt;/span&gt;(github&amp;nbsp;copilot)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;background-color: #ffffff; color: #6bacce; text-align: start;&quot; href=&quot;https://ios-development.tistory.com/1824&quot;&gt;VScode에 깃헙 코파일럿 활용 방법 (github copilot, 지침, 프롬프트)&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;github copilot 개념&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GitHub&amp;nbsp;Copilot은&amp;nbsp;GitHub과&amp;nbsp;OpenAI가&amp;nbsp;공동&amp;nbsp;개발한&amp;nbsp;AI&amp;nbsp;프로그래밍&amp;nbsp;도우미&lt;/li&gt;
&lt;li&gt;IDE에서&amp;nbsp;gpt5, claude code와 같은 것들을 사용할 수 있게 제공해주는것&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;github copilot의 기능&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;379&quot; data-start=&quot;138&quot;&gt;자동 코드 완성
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;379&quot; data-start=&quot;172&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;208&quot; data-start=&quot;172&quot;&gt;주석이나 함수 이름만 써도 나머지 코드를 자동으로 제안&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;525&quot; data-start=&quot;436&quot;&gt;자연어 설명 기반 코드 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;525&quot; data-start=&quot;462&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;525&quot; data-start=&quot;462&quot;&gt;&amp;ldquo;사용자 로그인 화면 만들기&amp;rdquo;처럼 자연어로 설명을 쓰면,&lt;br /&gt;그 설명에 맞는 코드를 자동으로 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;623&quot; data-start=&quot;527&quot;&gt;다양한 언어 지원
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;623&quot; data-start=&quot;547&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;623&quot; data-start=&quot;547&quot;&gt;Swift, Python, JavaScript, TypeScript, C++, Go, Rust 등 거의 모든 주요 언어를 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;728&quot; data-start=&quot;625&quot;&gt;IDE 통합
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;728&quot; data-start=&quot;625&quot;&gt;vscode, Xcode와 같은 IDE에 통합되어 코드맥락을 더욱 잘 파악하며 답변해줄수있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;github 로그인 &amp;gt; 프로필 클릭 &amp;gt; Copilot &amp;gt; Features 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1978&quot; data-origin-height=&quot;1394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C1x7p/dJMb9c2BoID/G2xySSXhLn7Ch4nq3Ss0M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C1x7p/dJMb9c2BoID/G2xySSXhLn7Ch4nq3Ss0M0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C1x7p/dJMb9c2BoID/G2xySSXhLn7Ch4nq3Ss0M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC1x7p%2FdJMb9c2BoID%2FG2xySSXhLn7Ch4nq3Ss0M0%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;1978&quot; height=&quot;1394&quot; data-origin-width=&quot;1978&quot; data-origin-height=&quot;1394&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Start Using Copilot Free 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evdCX1/dJMb9hpi19C/MBMQn8eDEusDLkbrVdjg11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evdCX1/dJMb9hpi19C/MBMQn8eDEusDLkbrVdjg11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evdCX1/dJMb9hpi19C/MBMQn8eDEusDLkbrVdjg11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FevdCX1%2FdJMb9hpi19C%2FMBMQn8eDEusDLkbrVdjg11%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;1772&quot; height=&quot;946&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용할수 있게 되었으므로 준비 완료
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 남은것은 IDE에서 사용하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfwSdy/dJMb9WMdnBC/sb8ZUZWLpHcBvvFJCWZ2xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfwSdy/dJMb9WMdnBC/sb8ZUZWLpHcBvvFJCWZ2xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfwSdy/dJMb9WMdnBC/sb8ZUZWLpHcBvvFJCWZ2xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfwSdy%2FdJMb9WMdnBC%2Fsb8ZUZWLpHcBvvFJCWZ2xk%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;2876&quot; height=&quot;1136&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;vscode 에서 사용하는 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;vscode &amp;gt; Extensions을 누르고, 검색창에 `github copilot` 입력
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 개 설치 (GitHub Copilot, GitHub Copilot Chat)&lt;/li&gt;
&lt;li&gt;`GitHub Copilot`하나만 설치하면 밑에껏도 자동으로 설치됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rScE7/dJMb9P0IqOo/XDevmJheJDg4fJXofMEOH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rScE7/dJMb9P0IqOo/XDevmJheJDg4fJXofMEOH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rScE7/dJMb9P0IqOo/XDevmJheJDg4fJXofMEOH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrScE7%2FdJMb9P0IqOo%2FXDevmJheJDg4fJXofMEOH1%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;1248&quot; height=&quot;750&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치하면 signin하라는 `&lt;span style=&quot;color: #777777; text-align: center;&quot;&gt;Sign in with GitHub to use GitHub Copilot&lt;/span&gt;` 알림이 뜨는데 수행하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;1228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6hvjB/dJMb9WenvgP/EkIGbA0UR0USp4ryA5H7Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6hvjB/dJMb9WenvgP/EkIGbA0UR0USp4ryA5H7Fk/img.png&quot; data-alt=&quot;Sign in with GitHub to use GitHub Copilot&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6hvjB/dJMb9WenvgP/EkIGbA0UR0USp4ryA5H7Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6hvjB%2FdJMb9WenvgP%2FEkIGbA0UR0USp4ryA5H7Fk%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;524&quot; height=&quot;787&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;1228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Sign in with GitHub to use GitHub Copilot&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cG7DE5/dJMb8XYF9df/kN22nw8IUKOtCJpyvQ11a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cG7DE5/dJMb8XYF9df/kN22nw8IUKOtCJpyvQ11a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cG7DE5/dJMb8XYF9df/kN22nw8IUKOtCJpyvQ11a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcG7DE5%2FdJMb8XYF9df%2FkN22nw8IUKOtCJpyvQ11a1%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;1194&quot; height=&quot;1026&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 알림이 안보이면?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cmd + shift + P 명령 팔레트 &amp;gt; github copilot을 검색하고 sign in 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1588&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTyguy/dJMb8Z91RBO/2ypmaROaNSe1Oke8uocLy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTyguy/dJMb8Z91RBO/2ypmaROaNSe1Oke8uocLy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTyguy/dJMb8Z91RBO/2ypmaROaNSe1Oke8uocLy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTyguy%2FdJMb8Z91RBO%2F2ypmaROaNSe1Oke8uocLy1%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;1588&quot; height=&quot;774&quot; data-origin-width=&quot;1588&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연동 완료
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오른쪽이 chat을 사용할수 있는 창&lt;/li&gt;
&lt;li&gt;cmd + option + B로 열고 닫을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L5pUn/dJMb9bWVxXh/NeZKSRU4C661f2B19TwY5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L5pUn/dJMb9bWVxXh/NeZKSRU4C661f2B19TwY5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L5pUn/dJMb9bWVxXh/NeZKSRU4C661f2B19TwY5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL5pUn%2FdJMb9bWVxXh%2FNeZKSRU4C661f2B19TwY5K%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;2876&quot; height=&quot;1698&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1698&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;활용하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ai 모델 변경하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;챗 아래쪽 모델 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;1540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lwIHU/dJMb9PGpN2u/6uaA0v3nczo3ydG6nufpZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lwIHU/dJMb9PGpN2u/6uaA0v3nczo3ydG6nufpZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lwIHU/dJMb9PGpN2u/6uaA0v3nczo3ydG6nufpZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlwIHU%2FdJMb9PGpN2u%2F6uaA0v3nczo3ydG6nufpZk%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;517&quot; height=&quot;690&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;1540&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러가지 모델 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XUyJ3/dJMb9WZKtAL/8t1RZUEszBBCzYglRcbHk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XUyJ3/dJMb9WZKtAL/8t1RZUEszBBCzYglRcbHk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XUyJ3/dJMb9WZKtAL/8t1RZUEszBBCzYglRcbHk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXUyJ3%2FdJMb9WZKtAL%2F8t1RZUEszBBCzYglRcbHk0%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;1384&quot; height=&quot;646&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>github</category>
      <category>GitHub Copilot</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>깃헙</category>
      <category>깃헙 코파일럿</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1822</guid>
      <comments>https://ios-development.tistory.com/1822#entry1822comment</comments>
      <pubDate>Wed, 29 Oct 2025 01:43:35 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 최적화 - 성능 모니터링 시스템 구축 사례 XCMetrics (스포티파이, XCMetrics 오픈소스)</title>
      <link>https://ios-development.tistory.com/1821</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;XCMetrics 오픈소스&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot; data-alt=&quot;XCMetrics를 통해 성능 관련 내용들을 시각화&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzjdo9%2FdJMb9Onaihj%2Fa29mSirMhEILtKUuWU7c71%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;1340&quot; height=&quot;778&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;XCMetrics를 통해 성능 관련 내용들을 시각화&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오픈소스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;github: &lt;a href=&quot;https://github.com/spotify/XCMetrics&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/spotify/XCMetrics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;스포티파이가 만든 오픈소스이며, 성능에 관해 실시간으로 모니터링 할 수 있는 시스템&lt;/li&gt;
&lt;li&gt;xcactivitylog 형식으로 저장된 Xcode 및 xcodebuild 로그를 파싱할 수 있는 도구인 XCLogParser를 기반으로 구축&lt;/li&gt;
&lt;li&gt;Spotify iOS 앱에서 약 100만 개의 빌드와 100억 개 이상의 단계를 수집했고, 이를 통해 프로젝트 구조 및 아키텍처와 관련하여 중요하고 정보에 기반한 결정을 내릴 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이점
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;xcactivitylog 파일에서 데이터를 추출하여 빌드 시간, 경고, 오류 및 기타 메타데이터를 원하는 방식으로 볼 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정렬, 검색이 가능하여, 어떤 부분이 빌드 시간이 오래걸리고 언제부터 문제가 있었는지 파악이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAId5Z/dJMb9QFhEfF/mApKBv61QoUdO4PJOkgK61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAId5Z/dJMb9QFhEfF/mApKBv61QoUdO4PJOkgK61/img.png&quot; data-alt=&quot;xcmetrics 콘솔&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAId5Z/dJMb9QFhEfF/mApKBv61QoUdO4PJOkgK61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAId5Z%2FdJMb9QFhEfF%2FmApKBv61QoUdO4PJOkgK61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;496&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;xcmetrics 콘솔&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;XCMetrics의 원리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode는 테스트, 프로덕션 환경 모두 xcodebuild는 &lt;u&gt;&lt;b&gt;xcactivitylog&lt;/b&gt;&lt;/u&gt;라는 로그 파일을 생성함&lt;/li&gt;
&lt;li&gt;xcactivitylog라는 로그 파일을 보면, 경고, 오류, 빌드 시간 등 유용한 성능에 관한 정보를 얻을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;XCMetrics 구조&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백엔드쪽은 Swift로 작성되어있고, multipart request를 통해 메타데이터를 첨부&lt;/li&gt;
&lt;li&gt;데이터베이스는 ProgresSQL이 사용되어 있으며, 데이터가 날짜별로 분기되어있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crTxnA/dJMb9XEkRce/wkNoL7JQYWs9s80An5xW1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crTxnA/dJMb9XEkRce/wkNoL7JQYWs9s80An5xW1K/img.png&quot; data-alt=&quot;https://engineering.atspotify.com/2021/1/introducing-xcmetrics-our-all-in-one-tool-for-tracking-xcode-build-metrics&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crTxnA/dJMb9XEkRce/wkNoL7JQYWs9s80An5xW1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrTxnA%2FdJMb9XEkRce%2FwkNoL7JQYWs9s80An5xW1K%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;1368&quot; height=&quot;540&quot; data-origin-width=&quot;1368&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://engineering.atspotify.com/2021/1/introducing-xcmetrics-our-all-in-one-tool-for-tracking-xcode-build-metrics&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스포티파이와 XCMetrics&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스포티파이는 아래 사진과 같이 코드베이스와 상태를 모니터링하기 위해 매일 사용되는 데이터 파이프라인과 대시보드가 존재
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;XCMetrics를 통해 로그를 파악하면서 프로젝트 구조에 대해서 많은 개선을 시도함&lt;/li&gt;
&lt;li&gt;빌드 숫자, 코드 커버리지, 통계, 용량, warnings, errors 등 파악에 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzjdo9/dJMb9Onaihj/a29mSirMhEILtKUuWU7c71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzjdo9%2FdJMb9Onaihj%2Fa29mSirMhEILtKUuWU7c71%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;1340&quot; height=&quot;778&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://github.com/spotify/XCMetrics&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/spotify/XCMetrics&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://engineering.atspotify.com/2021/1/introducing-xcmetrics-our-all-in-one-tool-for-tracking-xcode-build-metrics&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://engineering.atspotify.com/2021/1/introducing-xcmetrics-our-all-in-one-tool-for-tracking-xcode-build-metrics&lt;/a&gt;&lt;/p&gt;</description>
      <category>최적화하기</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>XCMetrics</category>
      <category>최적화</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1821</guid>
      <comments>https://ios-development.tistory.com/1821#entry1821comment</comments>
      <pubDate>Wed, 22 Oct 2025 01:06:26 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 최적화 - Instruments로 행 분석하는 방법 (Analyze hangs with Instruments)</title>
      <link>https://ios-development.tistory.com/1820</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;행이란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&gt;애플에서 제공하는 가이드)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVsnZw/btsQ67GKieW/H5nPe3Igyjg2MzhSwpnzO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVsnZw/btsQ67GKieW/H5nPe3Igyjg2MzhSwpnzO0/img.png&quot; data-alt=&quot;https://developer.apple.com/videos/play/wwdc2023/10248/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVsnZw/btsQ67GKieW/H5nPe3Igyjg2MzhSwpnzO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVsnZw%2FbtsQ67GKieW%2FH5nPe3Igyjg2MzhSwpnzO0%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;1504&quot; height=&quot;524&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;524&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://developer.apple.com/videos/play/wwdc2023/10248/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의미&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Instant&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;즉각적인&lt;/td&gt;
&lt;td&gt;반응이 바로 느껴질 정도로 빠름 (~100ms 이내)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Circumstantial&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상황에 따라 달라지는, 약간 느리지만 용인됨&lt;/td&gt;
&lt;td&gt;약간의 지연(~250ms)은 사용자가 느끼지만 불편하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Microhang&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;미세한 멈춤&lt;/td&gt;
&lt;td&gt;눈에 띄는 짧은 멈춤 (~500ms 미만)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Hang&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;완전한 멈춤(먹통)&lt;/td&gt;
&lt;td&gt;반응이 끊기거나 멈춘 듯한 상태 (~500ms 이상)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, 즉각적이려면 100ms 이내로 동작하게끔해야함&lt;/li&gt;
&lt;li&gt;또 &lt;u&gt;&lt;b&gt;행의 기준은 500ms 이상 걸리는 동작을 의미함&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;행 파악하는 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 알아본대로 500ms 이상 걸리는 작업을 행이라고 정의&lt;/li&gt;
&lt;li&gt;이 행은 Instruments의 Time Profiler에서 확인이 가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Time Profiler 관련 기초 내용은 이전 &lt;a href=&quot;https://ios-development.tistory.com/1819&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;포스팅 글&lt;/a&gt; 참고&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Instruemtns &amp;gt; Time Profiler 중 Hangs 부분)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCyDcu/btsQ6QLRZqw/fEIKrIKGjiIvMsPqwsnir0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCyDcu/btsQ6QLRZqw/fEIKrIKGjiIvMsPqwsnir0/img.png&quot; data-alt=&quot;https://developer.apple.com/videos/play/wwdc2023/10248/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCyDcu/btsQ6QLRZqw/fEIKrIKGjiIvMsPqwsnir0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCyDcu%2FbtsQ6QLRZqw%2FfEIKrIKGjiIvMsPqwsnir0%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;1512&quot; height=&quot;730&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://developer.apple.com/videos/play/wwdc2023/10248/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 보여지는 Severe Hang은 3.44초가 걸렸는데 단순히 오래걸린다는 의미에는 Too long 말고도 &lt;b&gt;Too often&lt;/b&gt;도 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Main Thread가 바쁜 경우&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3.44초가 걸린 행을 분석할때는 세 가지 관점으로 먼저 생각 필요
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오래 걸림 (Too long)&lt;/li&gt;
&lt;li&gt;자주 불림 (Too often)&lt;/li&gt;
&lt;li&gt;메인스레드가 blocked 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이것을 어떻게 구분할 것인가?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우선 메인 스레드가 block된지 유무는 쉽게 파악이 가능&lt;/li&gt;
&lt;li&gt;hangs 부분의 하위의 Main Thread의 그래프를 보면 hang 시점에 그래프가 들쑥날쑥 보이는 것과 아예 그래프가 없는 것으로 확인이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/er32Py/btsQ5EFKJCM/3jenlToR0qS8OKWyiNbgp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/er32Py/btsQ5EFKJCM/3jenlToR0qS8OKWyiNbgp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/er32Py/btsQ5EFKJCM/3jenlToR0qS8OKWyiNbgp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fer32Py%2FbtsQ5EFKJCM%2F3jenlToR0qS8OKWyiNbgp0%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;1526&quot; height=&quot;676&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오래 걸림 vs 자주 불림 구분 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;오래 걸림 (Too long)&lt;/td&gt;
&lt;td&gt;자주 불림 (Too often)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Flame Graph&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;가로로 긴 막대, 길게 이어짐&lt;/td&gt;
&lt;td&gt;짧은 막대가 반복적으로 여러 곳에 흩어짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Call Tree&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Calls 적음, Self Time 높음&lt;/td&gt;
&lt;td&gt;Calls 많음, Avg Time 낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Timeline&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;굵은 덩어리 하나로 CPU 점유&lt;/td&gt;
&lt;td&gt;얇은 점들이 계속 반복, 일정한 패턴&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 확인하는 방법: Time Profiler의 CPU Usage와 동일 (&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;이전&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1; text-align: left;&quot; href=&quot;https://ios-development.tistory.com/1819&quot;&gt;포스팅 글&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;참고)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://green1229.tistory.com/509&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://green1229.tistory.com/509&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2023/10248/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/videos/play/wwdc2023/10248/&lt;/a&gt;&lt;/p&gt;</description>
      <category>최적화하기</category>
      <category>analyze hangs</category>
      <category>hang</category>
      <category>instruments</category>
      <category>Instruments로 행 분석하는 방법</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>최적화</category>
      <category>행</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1820</guid>
      <comments>https://ios-development.tistory.com/1820#entry1820comment</comments>
      <pubDate>Wed, 15 Oct 2025 01:10:34 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 최적화 - Instrument의 Time Profiler</title>
      <link>https://ios-development.tistory.com/1819</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;Time Profiler&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode &amp;gt; Cmd + I로 Instrument 실행 &amp;gt; Time Profiler 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;1006&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxJh0i/btsQ3i3KwOm/cIh6zh7gvqAg9RQ2CZI0Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxJh0i/btsQ3i3KwOm/cIh6zh7gvqAg9RQ2CZI0Sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxJh0i/btsQ3i3KwOm/cIh6zh7gvqAg9RQ2CZI0Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxJh0i%2FbtsQ3i3KwOm%2FcIh6zh7gvqAg9RQ2CZI0Sk%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;1592&quot; height=&quot;1006&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;1006&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;창이 뜨면 Record 버튼을 눌러서 앱을 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Oct-08-2025 14-00-01.gif&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sIIM5/btsQ4pA2VqP/w4AQ8RORFbtXvDmQ2DOV91/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sIIM5/btsQ4pA2VqP/w4AQ8RORFbtXvDmQ2DOV91/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sIIM5/btsQ4pA2VqP/w4AQ8RORFbtXvDmQ2DOV91/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/sIIM5/btsQ4pA2VqP/w4AQ8RORFbtXvDmQ2DOV91/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;326&quot; data-filename=&quot;Oct-08-2025 14-00-01.gif&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중지 버튼을 눌러서 분석 중지&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Oct-08-2025 14-05-33.gif&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SvXJx/btsQ3fsot4L/Gc810qyuDdY0KRImUwwXy1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SvXJx/btsQ3fsot4L/Gc810qyuDdY0KRImUwwXy1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SvXJx/btsQ3fsot4L/Gc810qyuDdY0KRImUwwXy1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/SvXJx/btsQ3fsot4L/Gc810qyuDdY0KRImUwwXy1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1138&quot; height=&quot;604&quot; data-filename=&quot;Oct-08-2025 14-05-33.gif&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그래프를 보면 삐쭉 튀어나와있는 부분에 커서를 대면 시간이 얼마나 걸렸는지 알 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;1172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgFC5L/btsQ3zqAEYz/fFzWf2X7dOrdnxLLL7oSZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgFC5L/btsQ3zqAEYz/fFzWf2X7dOrdnxLLL7oSZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgFC5L/btsQ3zqAEYz/fFzWf2X7dOrdnxLLL7oSZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgFC5L%2FbtsQ3zqAEYz%2FfFzWf2X7dOrdnxLLL7oSZk%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;391&quot; height=&quot;455&quot; data-origin-width=&quot;1008&quot; data-origin-height=&quot;1172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 부분을 왼쪽마우스로 클릭하고 아래 로그를 보면 어떤 부분에서 시간이 걸렸는지 확인이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1768&quot; data-origin-height=&quot;1568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GMyae/btsQ5VeHvdw/JX2B0hVyAuAcePhUbAs5KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GMyae/btsQ5VeHvdw/JX2B0hVyAuAcePhUbAs5KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GMyae/btsQ5VeHvdw/JX2B0hVyAuAcePhUbAs5KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGMyae%2FbtsQ5VeHvdw%2FJX2B0hVyAuAcePhUbAs5KK%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;534&quot; height=&quot;474&quot; data-origin-width=&quot;1768&quot; data-origin-height=&quot;1568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;더 구체적으로 확인 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에 까지 알아본 방법은 대충 어떤 함수가 많이 걸리는지 알려주는데 더욱 구체적인 back trace를 보고싶은 경우는 아래처럼 처리가 필요&lt;/li&gt;
&lt;li&gt;Samples를 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2398&quot; data-origin-height=&quot;1694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uQ3Mz/btsQ2WT6da1/3aaw9TQ9KiAC0vFHHaINT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uQ3Mz/btsQ2WT6da1/3aaw9TQ9KiAC0vFHHaINT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uQ3Mz/btsQ2WT6da1/3aaw9TQ9KiAC0vFHHaINT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuQ3Mz%2FbtsQ2WT6da1%2F3aaw9TQ9KiAC0vFHHaINT0%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;2398&quot; height=&quot;1694&quot; data-origin-width=&quot;2398&quot; data-origin-height=&quot;1694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;1322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9ZiGv/btsQ5yYjKAT/UG60O9fiVpW69ad3d3rKa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9ZiGv/btsQ5yYjKAT/UG60O9fiVpW69ad3d3rKa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9ZiGv/btsQ5yYjKAT/UG60O9fiVpW69ad3d3rKa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9ZiGv%2FbtsQ5yYjKAT%2FUG60O9fiVpW69ad3d3rKa1%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;578&quot; height=&quot;635&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;1322&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Profile 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfU3ob/btsQ3axQRF3/EcoPvIgIksGJnEMKdemFG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfU3ob/btsQ3axQRF3/EcoPvIgIksGJnEMKdemFG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfU3ob/btsQ3axQRF3/EcoPvIgIksGJnEMKdemFG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfU3ob%2FbtsQ3axQRF3%2FEcoPvIgIksGJnEMKdemFG1%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;378&quot; height=&quot;400&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하단 로그를 보면 아래처럼 누적값으로 Weight가 표시되는데 가장 큰 weight가 증가한 start부분을 펼치기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt8nS5/btsQ4hXkvDd/o6xWfRUa9m7mMHvXhZKJk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt8nS5/btsQ4hXkvDd/o6xWfRUa9m7mMHvXhZKJk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt8nS5/btsQ4hXkvDd/o6xWfRUa9m7mMHvXhZKJk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt8nS5%2FbtsQ4hXkvDd%2Fo6xWfRUa9m7mMHvXhZKJk1%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;1084&quot; height=&quot;290&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;option + 왼쪽마우스 클릭하면 다 펼쳐짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1932&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmGQoa/btsQ2QfjNI8/stydfpBK1rbEkJ7QwTDbE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmGQoa/btsQ2QfjNI8/stydfpBK1rbEkJ7QwTDbE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmGQoa/btsQ2QfjNI8/stydfpBK1rbEkJ7QwTDbE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmGQoa%2FbtsQ2QfjNI8%2FstydfpBK1rbEkJ7QwTDbE1%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;1932&quot; height=&quot;784&quot; data-origin-width=&quot;1932&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 증가량이 많은 해당 부분을 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccs7UE/btsQ5DFlhVG/8MHCevl0K8FvYg9pReHDw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccs7UE/btsQ5DFlhVG/8MHCevl0K8FvYg9pReHDw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccs7UE/btsQ5DFlhVG/8MHCevl0K8FvYg9pReHDw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fccs7UE%2FbtsQ5DFlhVG%2F8MHCevl0K8FvYg9pReHDw0%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;1720&quot; height=&quot;686&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또 펼쳐서 계속 확인해보면 마침내 어디에서부터 시작되었는지와 이 이후에 어떤것들이 불렸는지 알 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgFBX9/btsQ2jB7EOK/thKj1UUVXFN6Yf0XGs3ny1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgFBX9/btsQ2jB7EOK/thKj1UUVXFN6Yf0XGs3ny1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgFBX9/btsQ2jB7EOK/thKj1UUVXFN6Yf0XGs3ny1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgFBX9%2FbtsQ2jB7EOK%2FthKj1UUVXFN6Yf0XGs3ny1%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;1848&quot; height=&quot;756&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호출 순서: 빨간 화살표
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Example1.heavyWork()가 호출되고나서 forEach 그다음 heavyWork() 그다음 fib() 순서로 파악이 가능하고 마침내 fib()에서 시간이 많이 걸렸다는 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pN7Mx/btsQ4iu9UAI/y4RlCOS4tzxHRzlIPhQeKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pN7Mx/btsQ4iu9UAI/y4RlCOS4tzxHRzlIPhQeKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pN7Mx/btsQ4iu9UAI/y4RlCOS4tzxHRzlIPhQeKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpN7Mx%2FbtsQ4iu9UAI%2Fy4RlCOS4tzxHRzlIPhQeKK%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;1528&quot; height=&quot;634&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>최적화하기</category>
      <category>Instrument</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>Time Profiler</category>
      <category>최적화</category>
      <category>타임 프로파일러</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1819</guid>
      <comments>https://ios-development.tistory.com/1819#entry1819comment</comments>
      <pubDate>Wed, 8 Oct 2025 21:04:07 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - SwiftUI] 헷갈리기 쉬운 frame(maxWidth: .infinity) 이해하기 (#Rounded 처리)</title>
      <link>https://ios-development.tistory.com/1817</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;frame(maxWidth: .infinity)의 의미&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;&quot;부모가 줄 수 있는 만큼 가로폭을 가득 채워라&quot;&lt;/b&gt;&lt;/u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;란 의미
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;frame(maxWidth: .infinity)는 최대 크기를 제한 한다는 느낌을 주는데 이 의미가 아님&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다른 예제)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 텍스트가 좌우 24 패딩을 갖는 뷰 구현?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;1550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rvahK/btsQYImlWpz/GIlX7GjunFWoq9dwyg2h81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rvahK/btsQYImlWpz/GIlX7GjunFWoq9dwyg2h81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rvahK/btsQYImlWpz/GIlX7GjunFWoq9dwyg2h81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrvahK%2FbtsQYImlWpz%2FGIlX7GjunFWoq9dwyg2h81%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;269&quot; height=&quot;589&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;1550&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기도 frame(maxWidth: .infinity)를 추가하여 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1759242986571&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;struct Example1: View {
    var body: some View {
        VStack {
            Text(&quot;Hello&quot;)
                .frame(maxWidth: .infinity) // &amp;lt;-
                .background(Color.red)
                .padding(.horizontal, 24)
            
            Text(&quot;World&quot;)
                .frame(maxWidth: .infinity)
                .background(Color.blue)
                .padding(.horizontal, 24)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Rounded 처리 방법&lt;/h4&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;1534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKoAHa/btsQYFpCYsI/rPgGVb5sXRkHoXKvPRv07k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKoAHa/btsQYFpCYsI/rPgGVb5sXRkHoXKvPRv07k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKoAHa/btsQYFpCYsI/rPgGVb5sXRkHoXKvPRv07k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKoAHa%2FbtsQYFpCYsI%2FrPgGVb5sXRkHoXKvPRv07k%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;328&quot; height=&quot;707&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;1534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구현하다보면 아래처럼 내부 콘텐츠에 fit하게 작성되는 경우가 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;1542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c37B8n/btsQVGRBj6M/yHkVRgwINkzfJ5KmJltfVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c37B8n/btsQVGRBj6M/yHkVRgwINkzfJ5KmJltfVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c37B8n/btsQVGRBj6M/yHkVRgwINkzfJ5KmJltfVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc37B8n%2FbtsQVGRBj6M%2FyHkVRgwINkzfJ5KmJltfVK%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;325&quot; height=&quot;694&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;1542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1759242602670&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            Text(&quot;title&quot;)
                .font(.title)

            Spacer()
                .frame(height: 8)

            Text(&quot;desc&quot;)
        }
        .padding(.horizontal, 15)
        .padding(.vertical, 20)
        .background(Color.blue)
        .clipShape(RoundedRectangle(cornerRadius: 16))
        .padding(.horizontal, 45)
    }
}&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;이럴땐 frame(maxWidth: .infinity)를 추가하여 해결이 가능&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;frame(maxWidth: .infinity)는 최대 크기를 고정한다는 느낌을 주는데 이 의미가 아님을 주의&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1759242620217&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            Text(&quot;title&quot;)
                .font(.title)

            Spacer()
                .frame(height: 8)

            Text(&quot;desc&quot;)
        }
        .padding(.horizontal, 15)
        .padding(.vertical, 20)
        .frame(maxWidth: .infinity) //&amp;lt;-
        .background(Color.blue)
        .clipShape(RoundedRectangle(cornerRadius: 16))
        .padding(.horizontal, 45)
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>frame(maxWidth: .infinity)</category>
      <category>ios</category>
      <category>swiftUI</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1817</guid>
      <comments>https://ios-development.tistory.com/1817#entry1817comment</comments>
      <pubDate>Wed, 1 Oct 2025 00:35:37 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - Swift] SwiftUI - Environmnet로 인터페이스 제공 방법 (#링크 텍스트)</title>
      <link>https://ios-development.tistory.com/1816</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;인터페이스 제공 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 링크 터치 이벤트를 처리하는 LinkDetectionText를 만들고 싶은 경우, LinkDetectionText 내부에서 해당 프로퍼티를 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;\.openURL&lt;/b&gt;의 정체: SwiftUI가 미리 정의한 EnvironmentKey&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1758548474097&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Environment(\.openURL) private var openURL&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;아래처럼 openURL 프로퍼티를 선언한 후 이 프로퍼티를 마치 클로저처럼 실행시키면, 외부에서 사용이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1758548568417&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct LinkDetectingText: View {
    @Environment(\.openURL) private var openURL // &amp;lt;-
    let text: String
    
    var body: some View {
        Text(makeAttributedString(from: text))
            .onOpenURL { url in
                openURL(url) // &amp;lt;-
            }
            .padding()
    }
    
    private func makeAttributedString(from string: String) -&amp;gt; AttributedString {
        ...
    }
}&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;외부에서는 openURL 키를 가지고 envionment 함수의 클로저에서 이벤트 핸들링이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1758548744336&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ContentView()
    .environment(\.openURL, OpenURLAction { url in
        print(&quot;링크 클릭됨:&quot;, url)
        return .handled
    })
    .padding()&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;openURL뿐만이 아닌 EnvironmentKey를 따로 정의하여 외부에 인터페이스 제공이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Sep-22-2025 22-47-21.gif&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMgCIA/btsQLeTAq14/xc0rq48Bi4kYZPrrGC59mk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMgCIA/btsQLeTAq14/xc0rq48Bi4kYZPrrGC59mk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMgCIA/btsQLeTAq14/xc0rq48Bi4kYZPrrGC59mk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bMgCIA/btsQLeTAq14/xc0rq48Bi4kYZPrrGC59mk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;590&quot; height=&quot;774&quot; data-filename=&quot;Sep-22-2025 22-47-21.gif&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체코드)&lt;/p&gt;
&lt;pre id=&quot;code_1758548854457&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import SwiftUI

@main
struct CounterDemoApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.openURL, OpenURLAction { url in
                    print(&quot;링크 클릭됨:&quot;, url)
                    return .handled
                })
                .padding()
        }
    }
}

struct LinkDetectingText: View {
    @Environment(\.openURL) private var openURL
    let text: String
    
    var body: some View {
        Text(makeAttributedString(from: text))
            .onOpenURL { url in
                openURL(url)
            }
            .padding()
    }
    
    private func makeAttributedString(from string: String) -&amp;gt; AttributedString {
        var attributed = AttributedString(string)
        if let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) {
            let matches = detector.matches(in: string, options: [], range: NSRange(location: 0, length: (string as NSString).length))
            for match in matches {
                if let range = Range(match.range, in: string),
                   let url = match.url {
                    let linkRange = attributed.range(of: String(string[range]))!
                    attributed[linkRange].link = url
                    attributed[linkRange].foregroundColor = .blue
                    attributed[linkRange].underlineStyle = .single
                }
            }
        }
        return attributed
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            LinkDetectingText(text: &quot;이건 그냥 텍스트고 https://apple.com 은 링크야.&quot;)
            LinkDetectingText(text: &quot;여기서도 https://google.com 클릭 가능&quot;)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS 응용 (SwiftUI)</category>
      <category>Environmnet</category>
      <category>ios</category>
      <category>swiftUI</category>
      <category>인터페이스 제공 방법</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1816</guid>
      <comments>https://ios-development.tistory.com/1816#entry1816comment</comments>
      <pubDate>Wed, 24 Sep 2025 01:47:54 +0900</pubDate>
    </item>
    <item>
      <title>[WWDC2025] SwiftUI 최적화 프로파일링 - Optimize SwiftUI performance with Instruments (4, Render Loop 개념, 업데이트 빈도수 파악하기)</title>
      <link>https://ios-development.tistory.com/1815</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;View 업데이트 빈도수 파악하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View의 body부분에서 업데이트가 너무 많게되면 아래 사진처럼 데드라인을 넘게되는 경우가 존재
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;-&amp;gt; hitch가 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2678&quot; data-origin-height=&quot;1286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbdcVJ/btsQwALcO5R/q7zjb9Lt9IozSJ7aB2ZDA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbdcVJ/btsQwALcO5R/q7zjb9Lt9IozSJ7aB2ZDA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbdcVJ/btsQwALcO5R/q7zjb9Lt9IozSJ7aB2ZDA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbdcVJ%2FbtsQwALcO5R%2Fq7zjb9Lt9IozSJ7aB2ZDA0%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;2678&quot; height=&quot;1286&quot; data-origin-width=&quot;2678&quot; data-origin-height=&quot;1286&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;업데이트 수 프로파일링 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View Body Updates 하위 트랙 선택&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;974&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUWDjO/btsQwP2qVEk/EsyJkwnZgGljJ5ovGbFkwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUWDjO/btsQwP2qVEk/EsyJkwnZgGljJ5ovGbFkwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUWDjO/btsQwP2qVEk/EsyJkwnZgGljJ5ovGbFkwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUWDjO%2FbtsQwP2qVEk%2FEsyJkwnZgGljJ5ovGbFkwk%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;1628&quot; height=&quot;974&quot; data-origin-width=&quot;1628&quot; data-origin-height=&quot;974&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빨간선 or 주황선 부분을 드래그하여 영역 선택&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2322&quot; data-origin-height=&quot;1060&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ScgRR/btsQzfZtOen/cmLHgykVRzMFYr4VWtJvVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ScgRR/btsQzfZtOen/cmLHgykVRzMFYr4VWtJvVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ScgRR/btsQzfZtOen/cmLHgykVRzMFYr4VWtJvVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FScgRR%2FbtsQzfZtOen%2FcmLHgykVRzMFYr4VWtJvVK%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;2322&quot; height=&quot;1060&quot; data-origin-width=&quot;2322&quot; data-origin-height=&quot;1060&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LandmarkListItemView에 Update Count가 30으로 찍혀있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwBvk3/btsQzv2aC73/lf7jSkZnEsyVylfGxbfb8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwBvk3/btsQzv2aC73/lf7jSkZnEsyVylfGxbfb8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwBvk3/btsQzv2aC73/lf7jSkZnEsyVylfGxbfb8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwBvk3%2FbtsQzv2aC73%2Flf7jSkZnEsyVylfGxbfb8K%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;1480&quot; height=&quot;786&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View코드를 작성할 때 이 부분을 확인해보면 내가 의도된 업데이트 카운트로 구현했는지 알 수 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약, List와 Row가 있는 뷰를 구현할 때 Row에 state하나만 바꿨을때, List전체가 업데이트 되었는지 파악하는 용도로도 사용이 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/306/&quot;&gt;https://developer.apple.com/videos/play/wwdc2025/306/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>ios</category>
      <category>Optimize SwiftUI performance with instruments</category>
      <category>Render Loop</category>
      <category>swiftUI</category>
      <category>SwiftUI 최적화 프로파일링</category>
      <category>업데이트 빈도수 파악하기</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1815</guid>
      <comments>https://ios-development.tistory.com/1815#entry1815comment</comments>
      <pubDate>Wed, 17 Sep 2025 01:24:13 +0900</pubDate>
    </item>
    <item>
      <title>[WWDC2025] SwiftUI 최적화 프로파일링 - Optimize SwiftUI performance with Instruments (3, Render Loop 개념, 화면이 끊기는 원리, hitch)</title>
      <link>https://ios-development.tistory.com/1814</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;프레임 드랍(Hitch)이 일어나는 과정 (Render Loop)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앱은 특정 싸이클마다 깨어나면서 이벤트를 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 싸이클마다 클릭 이벤트를 인식하고 UI를 업데이트&lt;/li&gt;
&lt;li&gt;이때 변경된 SwiftUI View의 body 프로퍼티를 실행함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2110&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqbMN1/btsQnx7ZkZq/zrkcSqsteiM965iu4yhXik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqbMN1/btsQnx7ZkZq/zrkcSqsteiM965iu4yhXik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqbMN1/btsQnx7ZkZq/zrkcSqsteiM965iu4yhXik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqbMN1%2FbtsQnx7ZkZq%2FzrkcSqsteiM965iu4yhXik%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;2110&quot; height=&quot;684&quot; data-origin-width=&quot;2110&quot; data-origin-height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 UI를 업데이트 하는 과정들은 각 주기 프레임 데드라인전에 완료되어야함&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉 데드라인 전에 UI가 업데이트 되는 것&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;렌더링 된 출력은 해당 데드라인 직후에 화면에 표출됨&lt;/b&gt;&lt;/u&gt; (주의: 첫번째 프레임에서 내부적인 UI 관련 업데이트를 하고 &lt;b&gt;화면에 보이는 것은 다음 프레임에서 수행&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2098&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byf6NV/btsQnGcOdqH/sglqtZN2DUa3WQXaUGei70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byf6NV/btsQnGcOdqH/sglqtZN2DUa3WQXaUGei70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byf6NV/btsQnGcOdqH/sglqtZN2DUa3WQXaUGei70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyf6NV%2FbtsQnGcOdqH%2FsglqtZN2DUa3WQXaUGei70%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;2098&quot; height=&quot;820&quot; data-origin-width=&quot;2098&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래와 같은 프레임 드랍 케이스의 Render Loop는?&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UI 업데이트 부분이 프레임 데드라인 후에 실행되었음&lt;/li&gt;
&lt;li&gt;이미 두 번째 프레임에서는 첫번째 UI 업데이트를 썼으므로 다음 업데이트는 3번째 프레임에서 시작해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pe4Gx/btsQo62Gv5t/xfNJ2vUmaM0yVYlXnMiKg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pe4Gx/btsQo62Gv5t/xfNJ2vUmaM0yVYlXnMiKg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pe4Gx/btsQo62Gv5t/xfNJ2vUmaM0yVYlXnMiKg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpe4Gx%2FbtsQo62Gv5t%2FxfNJ2vUmaM0yVYlXnMiKg1%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;1720&quot; height=&quot;604&quot; data-origin-width=&quot;1720&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 화면과 같이 2번째 loop에서 `Nothing to render!`됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주의) &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;첫번째 프레임에서 내부적인 UI 관련 업데이트를 하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;화면에 보이는 것은 다음 프레임에서 수행하기 때문에 두번째 프레임에서 화면에 아무것도 업데이트가 안되는것&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2670&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjDLEA/btsQmOhVom4/MjL797Rdilb0Yo7VF5Dsj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjDLEA/btsQmOhVom4/MjL797Rdilb0Yo7VF5Dsj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjDLEA/btsQmOhVom4/MjL797Rdilb0Yo7VF5Dsj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjDLEA%2FbtsQmOhVom4%2FMjL797Rdilb0Yo7VF5Dsj1%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;2670&quot; height=&quot;960&quot; data-origin-width=&quot;2670&quot; data-origin-height=&quot;960&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그럼 늦게 UI Update된 프레임은 화면에 언제 그려지는 걸까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;3번째 프레임도 아님&lt;/b&gt;&lt;i&gt;&lt;b&gt;: &lt;/b&gt;&lt;/i&gt;3번째 프레임에서는 Render 하는것에 자원을 사용하므로 결국 4번째 프레임에 그려짐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdWhQW/btsQnpCeKwi/n8vKGnXjK0cl3Mcxu7phC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdWhQW/btsQnpCeKwi/n8vKGnXjK0cl3Mcxu7phC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdWhQW/btsQnpCeKwi/n8vKGnXjK0cl3Mcxu7phC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdWhQW%2FbtsQnpCeKwi%2Fn8vKGnXjK0cl3Mcxu7phC0%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;1730&quot; height=&quot;640&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SwiftUI의 뷰 업데이트&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 알아본대로 Render Loop를 이해하여 SwiftUI의 Body부분에서 View Updates가 많이 일어나면 끊김 현상이 발생할 수 있다는 것을 이해&lt;/li&gt;
&lt;li&gt;Instrument를 통해 이런 부분을 발견하고 개선하는것이 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(... View Update Count를 보고 업데이트가 많이 일어나는 부분을 분석하는 내용은 다음 글에서 계속)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/306/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/videos/play/wwdc2025/306/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>Hitch</category>
      <category>Optimize SwiftUI performance with instruments</category>
      <category>Render Loop</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>SwiftUI 최적화 프로파일링</category>
      <category>화면이 끊기는 원리</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1814</guid>
      <comments>https://ios-development.tistory.com/1814#entry1814comment</comments>
      <pubDate>Wed, 10 Sep 2025 01:35:08 +0900</pubDate>
    </item>
    <item>
      <title>[WWDC2025] SwiftUI 최적화 프로파일링 - Optimize SwiftUI performance with Instruments (2)</title>
      <link>https://ios-development.tistory.com/1813</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;SwiftUI 프로파일링&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Instrument &amp;gt; SwiftUI 선택하고 프로파일 수행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저 SwiftUI 로 되어있는 꺽쇠를 클릭 &amp;gt; View Body Updates &amp;gt; 영역을 드래그하여 지정한 후 해당 영역 set Inspection Range And Zooms 클릭 &amp;gt; Time Profiler 클릭&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 포스팅 글 참고: &lt;a href=&quot;https://ios-development.tistory.com/1812&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ios-development.tistory.com/1812&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2864&quot; data-origin-height=&quot;1608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nIzwp/btsQedWbwVd/copmExYc5Hi5mBBo8kpgH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nIzwp/btsQedWbwVd/copmExYc5Hi5mBBo8kpgH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nIzwp/btsQedWbwVd/copmExYc5Hi5mBBo8kpgH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnIzwp%2FbtsQedWbwVd%2FcopmExYc5Hi5mBBo8kpgH1%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;2864&quot; height=&quot;1608&quot; data-origin-width=&quot;2864&quot; data-origin-height=&quot;1608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Time Profiler는 정기적으로 샘플을 추출하여 현재 실행중인 함수에 대한 분석을 시도
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뒤에서 나올 예제는 body가 실행되는 동안 프로파일링&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2538&quot; data-origin-height=&quot;1004&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brOJZF/btsQezRUyNT/7w0Ak35ecIZ2M2O49uXaik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brOJZF/btsQezRUyNT/7w0Ak35ecIZ2M2O49uXaik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brOJZF/btsQezRUyNT/7w0Ak35ecIZ2M2O49uXaik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrOJZF%2FbtsQezRUyNT%2F7w0Ak35ecIZ2M2O49uXaik%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;2538&quot; height=&quot;1004&quot; data-origin-width=&quot;2538&quot; data-origin-height=&quot;1004&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;WWDC 영상처럼 호출 스택이 여러가지가 표출됨&lt;/li&gt;
&lt;li&gt;이 중에서 살펴볼 것은 LandmarkListItemView이므로 command + F를 하여 검색&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2456&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dAp6qu/btsQcUQdG2s/22qIS6VDtZVbW1i4tVKreK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dAp6qu/btsQcUQdG2s/22qIS6VDtZVbW1i4tVKreK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dAp6qu/btsQcUQdG2s/22qIS6VDtZVbW1i4tVKreK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdAp6qu%2FbtsQcUQdG2s%2F22qIS6VDtZVbW1i4tVKreK%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;2456&quot; height=&quot;828&quot; data-origin-width=&quot;2456&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왼쪽을 보면 각 call stack안에 해당하는 프레임에 대한 소요 시간을 의미
&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;그 중에서 body부분이 관심이 있으므로 여기를 클릭해서 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clrHJg/btsQdRTriD0/LIlDRF1SLP3p616jvPsO4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clrHJg/btsQdRTriD0/LIlDRF1SLP3p616jvPsO4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clrHJg/btsQdRTriD0/LIlDRF1SLP3p616jvPsO4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclrHJg%2FbtsQdRTriD0%2FLIlDRF1SLP3p616jvPsO4K%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;2490&quot; height=&quot;894&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로파일링하기
&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;첫번째: 58.9%에서 73.7로 간 부분&lt;/li&gt;
&lt;li&gt;두번째: 31.6%에서 57.9%로 간 부분&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;802&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A9Epn/btsQe7Omp2p/gtAbqVLgzqwfjKOSpwQyE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A9Epn/btsQe7Omp2p/gtAbqVLgzqwfjKOSpwQyE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A9Epn/btsQe7Omp2p/gtAbqVLgzqwfjKOSpwQyE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA9Epn%2FbtsQe7Omp2p%2FgtAbqVLgzqwfjKOSpwQyE1%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;300&quot; height=&quot;672&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;802&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클릭하면 해당 부분의 코드가 표출&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2500&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IfSn3/btsQb6DGbSW/mlkVm8tEqKzIkx6Piabo51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IfSn3/btsQb6DGbSW/mlkVm8tEqKzIkx6Piabo51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IfSn3/btsQb6DGbSW/mlkVm8tEqKzIkx6Piabo51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIfSn3%2FbtsQb6DGbSW%2FmlkVm8tEqKzIkx6Piabo51%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;2500&quot; height=&quot;602&quot; data-origin-width=&quot;2500&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로파일링 결과 NSMeasurementFormatter 부분으로 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드에서 이 부분을 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clXfA3/btsQeeOmY1L/pGKAckoaczGTFOPKTvVMHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clXfA3/btsQeeOmY1L/pGKAckoaczGTFOPKTvVMHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clXfA3/btsQeeOmY1L/pGKAckoaczGTFOPKTvVMHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclXfA3%2FbtsQeeOmY1L%2FpGKAckoaczGTFOPKTvVMHK%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;2042&quot; height=&quot;608&quot; data-origin-width=&quot;2042&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;body에서 이 distance 변수를 뷰가 업데이트 될때마다 호출하고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1966&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjKV8V/btsQcXl2xsV/W2rqCcIfxDAQD440NecXX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjKV8V/btsQcXl2xsV/W2rqCcIfxDAQD440NecXX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjKV8V/btsQcXl2xsV/W2rqCcIfxDAQD440NecXX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjKV8V%2FbtsQcXl2xsV%2FW2rqCcIfxDAQD440NecXX0%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;1966&quot; height=&quot;768&quot; data-origin-width=&quot;1966&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로파일링을 하면 시간이 ms 단위로 적게 느껴지지만 이 시간들이 누적이 되면 사용성에 영향을 줄 수 있으므로 개선이 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(SwiftUI가 body를 실행하는데 걸리는 시간을 이해하는데 먼저 render loop 개념이 필요한데, 이 개념은 다음 글에서 계속..)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/306/&quot;&gt;https://developer.apple.com/videos/play/wwdc2025/306/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>Instrument</category>
      <category>ios</category>
      <category>profiling</category>
      <category>Render Loop</category>
      <category>swiftUI</category>
      <category>SwiftUI 최적화</category>
      <category>wwdc2025</category>
      <category>렌더링 루프</category>
      <category>프로파일링</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1813</guid>
      <comments>https://ios-development.tistory.com/1813#entry1813comment</comments>
      <pubDate>Wed, 3 Sep 2025 01:47:47 +0900</pubDate>
    </item>
    <item>
      <title>[WWDC2025] SwiftUI 최적화 프로파일링 - Optimize SwiftUI performance with Instruments (1)</title>
      <link>https://ios-development.tistory.com/1812</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;SwiftUI 최적화 방향&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SwiftUI 코드가 병목 현상인 시점을 식별 할 수 있는 방법을 중점으로 두고 SwiftUI가 효율적으로 작동하는 방법을 알아보는 것이 목적
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병목 현상) 애니메이션이 일시 중지되거나, 점프되거나 스크롤이 지연되는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;성능 문제를 식별하는 가장 좋은 방법은 &lt;b&gt;Xcode Instrument를 사용하여 앱을 프로파일링&lt;/b&gt;하는 것&lt;/li&gt;
&lt;li&gt;XCode 26부터 SwiftUI 프로파일링 할 수 있는 방법이 등장
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Instrument &amp;gt; SwiftUI 메뉴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;926&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HQbQj/btsP5KZNJYW/kK2n6h386bKRZHu8LGA3jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HQbQj/btsP5KZNJYW/kK2n6h386bKRZHu8LGA3jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HQbQj/btsP5KZNJYW/kK2n6h386bKRZHu8LGA3jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHQbQj%2FbtsP5KZNJYW%2FkK2n6h386bKRZHu8LGA3jk%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;1106&quot; height=&quot;926&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;926&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로파일링에서 볼 수 있는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Long View Body Updates: body 프로퍼티를 실행하는데 너무 오래 걸릴때 표시가 됨&lt;/li&gt;
&lt;li&gt;Long Representable Updates: View와 ViewController가 너무 오래 걸릴때 표시가 됨&lt;/li&gt;
&lt;li&gt;Other Long Updates: 모든 유형의 긴 update가 너무 오래 걸릴때 보여줌&lt;/li&gt;
&lt;li&gt;(주황색과 빨간색으로 표시됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2608&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HN5eN/btsP4ui58YH/PSc0mDMa1EhrtPtaTGFL01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HN5eN/btsP4ui58YH/PSc0mDMa1EhrtPtaTGFL01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HN5eN/btsP4ui58YH/PSc0mDMa1EhrtPtaTGFL01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHN5eN%2FbtsP4ui58YH%2FPSc0mDMa1EhrtPtaTGFL01%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;2608&quot; height=&quot;274&quot; data-origin-width=&quot;2608&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;프로파일링에서 볼 수 있는 것 -&lt;span&gt; Time Profiler&lt;/span&gt;&lt;/span&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;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;앱이 시간이 지남에 따라 CPU에서 수행하는 작업 샘플을 보여줌&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2730&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lXOft/btsP2D9pXH5/gmu05fy9mSyiAUdn7N6Pp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lXOft/btsP2D9pXH5/gmu05fy9mSyiAUdn7N6Pp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lXOft/btsP2D9pXH5/gmu05fy9mSyiAUdn7N6Pp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlXOft%2FbtsP2D9pXH5%2Fgmu05fy9mSyiAUdn7N6Pp0%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;2730&quot; height=&quot;452&quot; data-origin-width=&quot;2730&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SwiftUI Instrument requiremens&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Xcode 26 다운로드&lt;/li&gt;
&lt;li&gt;Xcode 열기 &amp;gt; Command I로 instrument 실행&lt;/li&gt;
&lt;li&gt;특정앱을 프로파일링하면, Long View Body Updates에서 주황색 선이 보여짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r7NyD/btsP4xUqBgL/t3Q7Zu843LyAKqMLY8Dbqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r7NyD/btsP4xUqBgL/t3Q7Zu843LyAKqMLY8Dbqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r7NyD/btsP4xUqBgL/t3Q7Zu843LyAKqMLY8Dbqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr7NyD%2FbtsP4xUqBgL%2Ft3Q7Zu843LyAKqMLY8Dbqk%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;1996&quot; height=&quot;738&quot; data-origin-width=&quot;1996&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;View Body Updates 부분을 클릭하면, 아래처럼 데이터가 보임&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2298&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lXS6r/btsP57HdWhl/yqLf6JwFuCPoVJTiOOlTU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lXS6r/btsP57HdWhl/yqLf6JwFuCPoVJTiOOlTU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lXS6r/btsP57HdWhl/yqLf6JwFuCPoVJTiOOlTU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlXS6r%2FbtsP57HdWhl%2FyqLf6JwFuCPoVJTiOOlTU0%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;2298&quot; height=&quot;944&quot; data-origin-width=&quot;2298&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Summary: View Body Updates 부분을 누르면 아래처럼 세분화하여 보기 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKennL/btsP4xz8d0Z/0TLdy7rZW7VZYb9dNHlBiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKennL/btsP4xz8d0Z/0TLdy7rZW7VZYb9dNHlBiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKennL/btsP4xz8d0Z/0TLdy7rZW7VZYb9dNHlBiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKennL%2FbtsP4xz8d0Z%2F0TLdy7rZW7VZYb9dNHlBiK%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;1480&quot; height=&quot;312&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;긴 업데이트가 표시되는 부분을 확인 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwutKX/btsP23mgp35/7zMomLa5aKRMLYDPIPP8J0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwutKX/btsP23mgp35/7zMomLa5aKRMLYDPIPP8J0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwutKX/btsP23mgp35/7zMomLa5aKRMLYDPIPP8J0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwutKX%2FbtsP23mgp35%2F7zMomLa5aKRMLYDPIPP8J0%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;1532&quot; height=&quot;218&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`-&amp;gt;` 오른쪽 화살표를 누르면 더 세분화하여 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1508&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dR5prq/btsP5q1BBAM/kXLu3HiUWtCQiuwB1Hg0EK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dR5prq/btsP5q1BBAM/kXLu3HiUWtCQiuwB1Hg0EK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dR5prq/btsP5q1BBAM/kXLu3HiUWtCQiuwB1Hg0EK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdR5prq%2FbtsP5q1BBAM%2FkXLu3HiUWtCQiuwB1Hg0EK%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;1508&quot; height=&quot;270&quot; data-origin-width=&quot;1508&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오른쪽 마우스 클릭 &amp;gt; `Set Inspection Range and Zoom` 클릭&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2432&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TIMRZ/btsP59yhhu3/VdvyJfDNZxLZou0AIWQ1W0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TIMRZ/btsP59yhhu3/VdvyJfDNZxLZou0AIWQ1W0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TIMRZ/btsP59yhhu3/VdvyJfDNZxLZou0AIWQ1W0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTIMRZ%2FbtsP59yhhu3%2FVdvyJfDNZxLZou0AIWQ1W0%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;2432&quot; height=&quot;652&quot; data-origin-width=&quot;2432&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Instrument 그래프에 해당 부분으로 펼쳐서 보여짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2868&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sEDeZ/btsP4seLbal/fHB2kXttEN5dpY2TUh2iGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sEDeZ/btsP4seLbal/fHB2kXttEN5dpY2TUh2iGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sEDeZ/btsP4seLbal/fHB2kXttEN5dpY2TUh2iGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsEDeZ%2FbtsP4seLbal%2FfHB2kXttEN5dpY2TUh2iGk%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;2868&quot; height=&quot;946&quot; data-origin-width=&quot;2868&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(다음 글에서 계속..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/306/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/videos/play/wwdc2025/306/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>ios</category>
      <category>Optimize SwiftUI performance with instruments</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>wwdc2025</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1812</guid>
      <comments>https://ios-development.tistory.com/1812#entry1812comment</comments>
      <pubDate>Wed, 27 Aug 2025 01:46:31 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] 디스플레이 확대/축소, 화면 확대 모드 감지 방법 (더 큰 텍스트, UIScreen.main.scale, UIScreen.main.nativeScale)</title>
      <link>https://ios-development.tistory.com/1811</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;더 큰 텍스트 효과란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;더 큰 텍스트 효과&lt;/b&gt; 사용 시, 시스템 전체에 영향이 가서 아래처럼 UILabel같은 컴포넌트들이 커짐&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;더 큰 텍스트 효과&lt;/b&gt; 적용 방법은 아래에서 설명&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgU3Y6/btsPTBi8IlF/RlED1KRrEnDKsxksMFKw3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgU3Y6/btsPTBi8IlF/RlED1KRrEnDKsxksMFKw3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgU3Y6/btsPTBi8IlF/RlED1KRrEnDKsxksMFKw3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgU3Y6%2FbtsPTBi8IlF%2FRlED1KRrEnDKsxksMFKw3K%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;1170&quot; height=&quot;2532&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;2079&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8FXmk/btsPUow2riY/vikTZfc3VmKA9dLH0HP9v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8FXmk/btsPUow2riY/vikTZfc3VmKA9dLH0HP9v0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8FXmk/btsPUow2riY/vikTZfc3VmKA9dLH0HP9v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8FXmk%2FbtsPUow2riY%2FvikTZfc3VmKA9dLH0HP9v0%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;960&quot; height=&quot;2079&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;2079&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1590&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eFO6X2/btsPWeUjodk/iO8KJH8pfpAkUQJDQVpV91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eFO6X2/btsPWeUjodk/iO8KJH8pfpAkUQJDQVpV91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eFO6X2/btsPWeUjodk/iO8KJH8pfpAkUQJDQVpV91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeFO6X2%2FbtsPWeUjodk%2FiO8KJH8pfpAkUQJDQVpV91%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;742&quot; height=&quot;1590&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;1590&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;1602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BF7En/btsPTC3nFs7/V4nTk0kLONUDhpjpuScbGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BF7En/btsPTC3nFs7/V4nTk0kLONUDhpjpuScbGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BF7En/btsPTC3nFs7/V4nTk0kLONUDhpjpuScbGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBF7En%2FbtsPTC3nFs7%2FV4nTk0kLONUDhpjpuScbGk%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;752&quot; height=&quot;1602&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;1602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설정 &amp;gt; 디스플레이 및 밝기 &amp;gt; 디스플레이 확대/축소 &amp;gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be7g9g/btsPSPoFT7o/8vHD8ds8jIkaAg9PkF8QLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be7g9g/btsPSPoFT7o/8vHD8ds8jIkaAg9PkF8QLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be7g9g/btsPSPoFT7o/8vHD8ds8jIkaAg9PkF8QLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe7g9g%2FbtsPSPoFT7o%2F8vHD8ds8jIkaAg9PkF8QLK%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;442&quot; height=&quot;957&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M10HR/btsPTy01NRV/bKrbuBOroHCOtnhXAbDZc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M10HR/btsPTy01NRV/bKrbuBOroHCOtnhXAbDZc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M10HR/btsPTy01NRV/bKrbuBOroHCOtnhXAbDZc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM10HR%2FbtsPTy01NRV%2FbKrbuBOroHCOtnhXAbDZc1%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;496&quot; height=&quot;1081&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7737.PNG&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AoTNV/btsPVflM2dp/9Kw0B9phR9eLcxn5QYRyv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AoTNV/btsPVflM2dp/9Kw0B9phR9eLcxn5QYRyv1/img.png&quot; data-alt=&quot;더 큰 텍스트 선택 시, 적용됨&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AoTNV/btsPVflM2dp/9Kw0B9phR9eLcxn5QYRyv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAoTNV%2FbtsPVflM2dp%2F9Kw0B9phR9eLcxn5QYRyv1%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;395&quot; height=&quot;855&quot; data-filename=&quot;IMG_7737.PNG&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;더 큰 텍스트 선택 시, 적용됨&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;코드에서 확대/축소 감지 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UIScreen.main.nativeScale 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어&amp;nbsp;디스플레이가&amp;nbsp;렌더링하는&amp;nbsp;원래&amp;nbsp;배율을&amp;nbsp;의미&lt;/li&gt;
&lt;li&gt;디스플레이 확대/축소에서 확대 옵션을 켜면 3.0이 3.65625으로 나옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;cf) 일반적으로 많이 아는 UIScreen.main.scale은 UIKit이 사용하는 기본 좌표계(points)와 실제 픽셀(pixels)의 배율을 의미
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반 Retina 디스플레이: scale = 2.0&lt;/li&gt;
&lt;li&gt;Super Retina (iPhone X 이후): scale = 3.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아래와같이 UIScreen의 확장으로 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1755411629132&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;extension UIScreen {
    static var isDisplayZoomed: Bool {
        let screen = UIScreen.main
        return abs(screen.nativeScale - screen.scale) &amp;gt; .ulpOfOne
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;`ulpOfOne`은 0에 가까운 값이며 부동소수점 오차가 있을 수 있기에 이 것을 사용한 것&lt;/li&gt;
&lt;li&gt;예) 3.0 - 2.9999999999999996 &amp;rarr; 사람이 보기엔 같지만, 기계적으로는 차이가 존재&lt;/li&gt;
&lt;li&gt;이런 미세한 차이를 &quot;사실상 0&quot; 으로 처리하기 위해 ulpOfOne 을 임계값으로 둔 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;차이가&amp;nbsp;ulpOfOne&amp;nbsp;이하&amp;nbsp;&amp;rarr;&amp;nbsp;사실상&amp;nbsp;같은&amp;nbsp;값&amp;nbsp;(확대&amp;nbsp;모드&amp;nbsp;아님)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;차이가&amp;nbsp;ulpOfOne&amp;nbsp;초과&amp;nbsp;&amp;rarr;&amp;nbsp;의미&amp;nbsp;있는&amp;nbsp;차이&amp;nbsp;(확대&amp;nbsp;모드임)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>iOS 응용 (swift)</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>uiscreen.main.nativescale</category>
      <category>UIScreen.main.scale</category>
      <category>더 큰 텍스트</category>
      <category>디스플레이 확대/축소</category>
      <category>화면 확대 모드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1811</guid>
      <comments>https://ios-development.tistory.com/1811#entry1811comment</comments>
      <pubDate>Wed, 20 Aug 2025 01:22:39 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] WWDC2025 정리 - 백그라운드에서 작업하는 방법 4 (Request background runtime, beginBackgroundTask)</title>
      <link>https://ios-development.tistory.com/1810</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;iOS 26의 BGContinuedProcessingTask&lt;/h4&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;앱은 백그라운드 진입 후에도 시스템은 UI를 통해 진행 상황을 표시&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 앱에서 내보내기 설정 &amp;gt; 백그라운드 진입 시 상단에 진행 상태 표시해주는 `Journal` 앱&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드에서 언제든 작업을 취소할 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ogSWh/btsPL2OvfZP/UdowbG6EMMd7Ges3aAZg5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ogSWh/btsPL2OvfZP/UdowbG6EMMd7Ges3aAZg5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ogSWh/btsPL2OvfZP/UdowbG6EMMd7Ges3aAZg5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FogSWh%2FbtsPL2OvfZP%2FUdowbG6EMMd7Ges3aAZg5K%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;295&quot; height=&quot;591&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;BGContinuedProcessingTask의 특징&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명확한 사용자 행동으로 시작 (버튼, 클릭 등)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예) 파일 추출, sns 업로드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자는 작업이 자동으로 시작되리라 기대하지 않음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BGContinuedProcessingTask으로 안되는 예) 백업, 사진 동기화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;즉 예상하지 못하는 작업을 이 API에는 사용하면 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;BGContinuedProcessingTask 사용 방법&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1. info.plist에서 작업 식별자를 추가
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Permitted background task scheduler identifiers 키 값으로 value에는 앱 bundle id로 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2540&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPJiol/btsPO8fpeX3/pIxTm0uaJHRg88Ctlxyo6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPJiol/btsPO8fpeX3/pIxTm0uaJHRg88Ctlxyo6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPJiol/btsPO8fpeX3/pIxTm0uaJHRg88Ctlxyo6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPJiol%2FbtsPO8fpeX3%2FpIxTm0uaJHRg88Ctlxyo6k%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;2540&quot; height=&quot;648&quot; data-origin-width=&quot;2540&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2. BGTaskScheduler를 사용하고 클로저 안에서 수행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만료되었을때 처리도 필요하여(아래에서 나올 예정) 아래처럼 shouldContinue라는 플래그를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1W3u0/btsPLj4iQYo/k8mR4WRyJ6cwK4HjWaqqZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1W3u0/btsPLj4iQYo/k8mR4WRyJ6cwK4HjWaqqZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1W3u0/btsPLj4iQYo/k8mR4WRyJ6cwK4HjWaqqZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1W3u0%2FbtsPLj4iQYo%2Fk8mR4WRyJ6cwK4HjWaqqZ1%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;1688&quot; height=&quot;1292&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만료되었을때 처리인 setTaskCompleted(success:)를 반드시 호출해주어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;908&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9DCI1/btsPOaSgimR/bi0djNpxLaxfa5QTkyZvB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9DCI1/btsPOaSgimR/bi0djNpxLaxfa5QTkyZvB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9DCI1/btsPOaSgimR/bi0djNpxLaxfa5QTkyZvB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9DCI1%2FbtsPOaSgimR%2Fbi0djNpxLaxfa5QTkyZvB1%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;1602&quot; height=&quot;908&quot; data-origin-width=&quot;1602&quot; data-origin-height=&quot;908&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3. UI 띄우기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BGContinueProcessingTaskRequest 인스턴스의 파라미터에 id에는 info.plist에 입력한 bundle id 입력&lt;/li&gt;
&lt;li&gt;백그라운드에서 사용자가 볼 제목인 title, subtitle을 입력&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UftAe/btsPOE6FhfZ/V3kRUw3LI6rSP6sSGtg2OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UftAe/btsPOE6FhfZ/V3kRUw3LI6rSP6sSGtg2OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UftAe/btsPOE6FhfZ/V3kRUw3LI6rSP6sSGtg2OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUftAe%2FbtsPOE6FhfZ%2FV3kRUw3LI6rSP6sSGtg2OK%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;1442&quot; height=&quot;400&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처리 전략 설정하고 BGTaskScheduler에 submit하면 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WK8w3/btsPLC3QeXj/oxHvDNgRv6SzqXLhjjtan0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WK8w3/btsPLC3QeXj/oxHvDNgRv6SzqXLhjjtan0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WK8w3/btsPLC3QeXj/oxHvDNgRv6SzqXLhjjtan0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWK8w3%2FbtsPLC3QeXj%2FoxHvDNgRv6SzqXLhjjtan0%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;518&quot; height=&quot;128&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;128&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;백그라운드 GPU&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드에서도 GPU를 사용할 수 있는데 이것은 Xcode 프로젝트 설정에서 백그라운드 GPU 기능을 추가해주어야함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnwpLw/btsPNDHbyZ6/6KvldEYbOi8fhq3BYKo4q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnwpLw/btsPNDHbyZ6/6KvldEYbOi8fhq3BYKo4q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnwpLw/btsPNDHbyZ6/6KvldEYbOi8fhq3BYKo4q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnwpLw%2FbtsPNDHbyZ6%2F6KvldEYbOi8fhq3BYKo4q0%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;2490&quot; height=&quot;462&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 레벨에서는 supportedResource로 체크한 후 reqruiedResources에 .gpu할당하여 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci3N2U/btsPMRFNFca/XAAkW3om0M9VHaKrrOuPDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci3N2U/btsPMRFNFca/XAAkW3om0M9VHaKrrOuPDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci3N2U/btsPMRFNFca/XAAkW3om0M9VHaKrrOuPDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci3N2U%2FbtsPMRFNFca%2FXAAkW3om0M9VHaKrrOuPDk%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;698&quot; height=&quot;366&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2025/227/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/videos/play/wwdc2025/227/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>backround</category>
      <category>ios</category>
      <category>Permitted background task scheduler identifiers</category>
      <category>SWIFT</category>
      <category>swiftUI</category>
      <category>백그라운드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1810</guid>
      <comments>https://ios-development.tistory.com/1810#entry1810comment</comments>
      <pubDate>Wed, 13 Aug 2025 01:08:00 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] WWDC2025 정리 - 백그라운드에서 작업하는 방법 3 (Request background runtime, beginBackgroundTask)</title>
      <link>https://ios-development.tistory.com/1809</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;Request background runtime&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드에서 특정 처리를 하고싶은 경우 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드에서 생성된 데이터를 바탕으로 ML을 생성하는 등의 처리를 하고 싶은 경우 사용&lt;/li&gt;
&lt;li&gt;백그라운드에서 DB를 클리어하고싶은 경우 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;964&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rPu26/btsPFu4EFZa/rRHHsGbDIpphZb9Z0UKfhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rPu26/btsPFu4EFZa/rRHHsGbDIpphZb9Z0UKfhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rPu26/btsPFu4EFZa/rRHHsGbDIpphZb9Z0UKfhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrPu26%2FbtsPFu4EFZa%2FrRHHsGbDIpphZb9Z0UKfhk%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;1472&quot; height=&quot;964&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;964&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;등록 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AppDelegate에서 &lt;b&gt;forTaskWithIDentifier&lt;/b&gt;로 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lmOrr/btsPE30KJJ3/trTlfWadN66qKKr49F1VNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lmOrr/btsPE30KJJ3/trTlfWadN66qKKr49F1VNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lmOrr/btsPE30KJJ3/trTlfWadN66qKKr49F1VNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlmOrr%2FbtsPE30KJJ3%2FtrTlfWadN66qKKr49F1VNK%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;2542&quot; height=&quot;1220&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;closure부분에 런타임에 호출할 내용만 작성해주면 완료&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2540&quot; data-origin-height=&quot;1256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rlvRN/btsPELFYgE5/JeazGz5uX9B2WmABqMTVm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rlvRN/btsPELFYgE5/JeazGz5uX9B2WmABqMTVm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rlvRN/btsPELFYgE5/JeazGz5uX9B2WmABqMTVm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrlvRN%2FbtsPELFYgE5%2FJeazGz5uX9B2WmABqMTVm0%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;2540&quot; height=&quot;1256&quot; data-origin-width=&quot;2540&quot; data-origin-height=&quot;1256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;아래처럼&lt;span&gt; &lt;/span&gt;&lt;/span&gt;request를 만들고 submit하면 동작이됨
&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;requiresNetworkConnectivity&lt;/b&gt;나 &lt;b&gt;requiresExternalPower&lt;/b&gt; 파라미터에 값을 세팅하여 섬세한 처리가 가능&lt;/li&gt;
&lt;li&gt;ex) 작업이 지연에 민감하지 않은 경우? &amp;gt; 충전 중이면서 네트워크에 연결됐을 때만 작업이 실행되도록 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcJoZu/btsPDV99KFj/BK0NFvEoril5jf5C4BIDWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcJoZu/btsPDV99KFj/BK0NFvEoril5jf5C4BIDWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcJoZu/btsPDV99KFj/BK0NFvEoril5jf5C4BIDWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcJoZu%2FbtsPDV99KFj%2FBK0NFvEoril5jf5C4BIDWK%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;1914&quot; height=&quot;640&quot; data-origin-width=&quot;1914&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;beginBackgroundTask&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드 작업 시작 및 종료 API&lt;/li&gt;
&lt;li&gt;백그라운드로 전환되었을때 복구가 어려운 작업을 마무리할 수 있게 도와주는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) DB에 관한 처리를 진행하다가 작업이 중단되면 파일을 닫는 처리가 누락될 수 있는데 이 API를 통해서 닫는 처리를 수월하게 할 수 있음&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약 아래처럼 export.saveState()로 상태를 안전하게 저장해야하는경우?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;248&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rvQWo/btsPEMZfcPM/Kq8TMPig0LXmOROztIPE0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rvQWo/btsPEMZfcPM/Kq8TMPig0LXmOROztIPE0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rvQWo/btsPEMZfcPM/Kq8TMPig0LXmOROztIPE0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrvQWo%2FbtsPEMZfcPM%2FKq8TMPig0LXmOROztIPE0K%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;248&quot; height=&quot;82&quot; data-origin-width=&quot;248&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래처럼 &lt;b&gt;beginBackgroundTask&lt;/b&gt;로 감싸면 시스템에 중요한 작업이 진행 중임을 알릴 수 있고 중단을 피할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;1132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SvLj8/btsPEvQUfPu/vI2ge8DlGzK1MzCak6DIv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SvLj8/btsPEvQUfPu/vI2ge8DlGzK1MzCak6DIv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SvLj8/btsPEvQUfPu/vI2ge8DlGzK1MzCak6DIv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSvLj8%2FbtsPEvQUfPu%2FvI2ge8DlGzK1MzCak6DIv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;585&quot; height=&quot;452&quot; data-origin-width=&quot;1466&quot; data-origin-height=&quot;1132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2025/227/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/videos/play/wwdc2025/227/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>Background</category>
      <category>background run time</category>
      <category>beginBackgroundTask</category>
      <category>ios</category>
      <category>Request background runtime</category>
      <category>SWIFT</category>
      <category>wwdc 2025</category>
      <category>wwdc2025</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1809</guid>
      <comments>https://ios-development.tistory.com/1809#entry1809comment</comments>
      <pubDate>Wed, 6 Aug 2025 01:59:50 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] WWDC2025 정리 - 백그라운드에서 작업하는 방법 2 (background)</title>
      <link>https://ios-development.tistory.com/1808</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;백그라운드 처리를 할때 고려하는것&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;공유 자원 (Memory, CPU, 네트워크 대역폭, 저전력 모드, 적은 데이터 모드)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 공유 자원 예시 - 포그라운드 관점&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드에 너무 많은 자원을 사용하면 비효율적으로 처리가 될 뿐 아니라 포그라운드 경험과도 충돌되므로 백그라운드에 있는것들 종료할 수 있음&lt;/li&gt;
&lt;li&gt;때문에 백그라운드 작업을 최소화하여 메모리 사용량을 줄여야함&lt;/li&gt;
&lt;li&gt;또한 사용자가 저전력 모드를 키는 성격을 고려하여 사용자 관점에서 생각하며 설계해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;애플에서 권고하는 백그라운드 처리 방향&lt;/h4&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2598&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y2QUn/btsPB8NGlS6/rNvja3JX6ur3nH45K7HX10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y2QUn/btsPB8NGlS6/rNvja3JX6ur3nH45K7HX10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y2QUn/btsPB8NGlS6/rNvja3JX6ur3nH45K7HX10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY2QUn%2FbtsPB8NGlS6%2FrNvja3JX6ur3nH45K7HX10%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;2598&quot; height=&quot;668&quot; data-origin-width=&quot;2598&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백그라운드 작업을 한다는 것은 &lt;i&gt;&lt;u&gt;&lt;b&gt;런타임 기회가 생길 때마다 점진적 진행이 가능해야함&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;(시스템 조건과 우선순위를 이해하고 적응할수록 작업 성공률은 더욱 높아짐)&lt;/li&gt;
&lt;li&gt;작업은 작고 가볍게 유지할 것&lt;/li&gt;
&lt;li&gt;필요 사항은 명확히 전달해야할 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;백그라운드 작업을 할 때 체크리스트&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 작업은 누가 시작했는가?&lt;/li&gt;
&lt;li&gt;명시적으로 시작된 작업인가? 아니면 나중에 실행해도 되는 선택적 작업인가?&lt;/li&gt;
&lt;li&gt;작업 소요 시간은 얼마나 되는가?&lt;/li&gt;
&lt;li&gt;작업은 앱 상태나 최신도에 중요한가?&lt;/li&gt;
&lt;li&gt;이 작업은 사용자의 동의나 입력이 필요한가? (필요하면 백그라운드 런타임은 적절하지 않음)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Background API 1) BGAppRefreshTask - 새로고침에 사용&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BGAppRefreshTask API
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로고침에 사용 &amp;gt; 서버에서 조용히 콘텐츠를 불러오는 용도&lt;/li&gt;
&lt;li&gt;자주 사용하는 앱 일수록 작업이 예약될 확률이 높아짐 (시스템에서 빈도수가 많은 앱 위주로 우선순위를 정함)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byDudH/btsPAZKKfFN/kE8QxkTdiYj4NpNDJrZf71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byDudH/btsPAZKKfFN/kE8QxkTdiYj4NpNDJrZf71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byDudH/btsPAZKKfFN/kE8QxkTdiYj4NpNDJrZf71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyDudH%2FbtsPAZKKfFN%2FkE8QxkTdiYj4NpNDJrZf71%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;557&quot; height=&quot;348&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SwiftUI 코드: .backgroundTask를 사용하여 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;앱이 백그라운드일 때 시스템은 해당 클로저를 호출함&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;1114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9qMMV/btsPA0v7Gtp/0zHPIOdawqZ8oMZvLcQlQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9qMMV/btsPA0v7Gtp/0zHPIOdawqZ8oMZvLcQlQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9qMMV/btsPA0v7Gtp/0zHPIOdawqZ8oMZvLcQlQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9qMMV%2FbtsPA0v7Gtp%2F0zHPIOdawqZ8oMZvLcQlQ0%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;2060&quot; height=&quot;1114&quot; data-origin-width=&quot;2060&quot; data-origin-height=&quot;1114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Background API 2) Background Push Notification&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에서 새 콘텐츠 알림을 보낼때, 시스템이 적절한 시점에 앱을 깨워 콘텐츠를 가져오게함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BGAppRefreshTask와는 다르게 데이터를 직접 요청하는 게 아니라 업데이트가 푸시되는 형식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;새로운 원격 콘텐츠가 있다는 신호로 씀
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1) 새로운 원격 콘텐츠가 있다는 신호&lt;/li&gt;
&lt;li&gt;2) 낮은 우선순위 작업이므로 과부하와 배터리 소모를 최소화함&lt;/li&gt;
&lt;li&gt;3) 사용자가 앱을 종료하면 시스템은 그 의도를 존중하여 앱이 다시 실행되기 전까지는 알림을 전달하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2025/227/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/videos/play/wwdc2025/227/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>.backgroundTask</category>
      <category>Background</category>
      <category>background API</category>
      <category>wwdc</category>
      <category>wwdc2025</category>
      <category>wwdc25</category>
      <category>백그라운드</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1808</guid>
      <comments>https://ios-development.tistory.com/1808#entry1808comment</comments>
      <pubDate>Wed, 30 Jul 2025 01:20:15 +0900</pubDate>
    </item>
    <item>
      <title>[iOS - swift] WWDC2025 정리 - 백그라운드에서 작업하는 방법 1 (background)</title>
      <link>https://ios-development.tistory.com/1807</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;백그라운드 작업이란?&lt;/h4&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;앱은 일시중단되며,&quot;&lt;b&gt;Suspended&lt;/b&gt;&quot; CPU를 사용하지 않게됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배터리를 보호하고 개인 정보를 지키는 역할&lt;/li&gt;
&lt;li&gt;포그라운드 앱에 리소스를 확보해 줌&lt;/li&gt;
&lt;li&gt;(앱은 일시중단 전 작업을 마무리할 수 있도록 백그라운드 실행 시간을 요청할 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;1040&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MCw5D/btsPp5kiZnj/esCxRt6jqWuxVVK30QjNWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MCw5D/btsPp5kiZnj/esCxRt6jqWuxVVK30QjNWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MCw5D/btsPp5kiZnj/esCxRt6jqWuxVVK30QjNWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMCw5D%2FbtsPp5kiZnj%2FesCxRt6jqWuxVVK30QjNWK%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;1462&quot; height=&quot;1040&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;1040&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위처럼 백그라운드 상태를 잘 사용하려면 시스템이 리소스를 어떻게 우선순위화하고 관리하는지, 앱 안에서 무엇을 할 수 있는지 이해하는것이 좋음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;백그라운드를 이해하는 핵심&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플이 백그라운드 상태를 만드는 목적의 핵심은 `&lt;u&gt;&lt;b&gt;배터리 수명&lt;/b&gt;&lt;/u&gt;`을 보호하고 `&lt;u&gt;&lt;b&gt;성능을 최적화&lt;/b&gt;&lt;/u&gt;`하여 &lt;u&gt;&lt;b&gt;부드럽고 반응성 있는 사용 경험&lt;/b&gt;&lt;/u&gt;을 유지하는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;때문에 백그라운드 실행은 보장되지 않음&lt;/li&gt;
&lt;li&gt;기회가 있을 때만 허용되고 대부분은 재량에 따라 엄격히 관리됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;시스템과 협력하는 방향&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 기본적인 제약은 &lt;b&gt;에너지&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex 에너지) 모든 작업, CPU 사이클, GPU 렌더링, 네트워크 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;백그라운드 런타임은 제한적이므로 할 일은 작고 명확한 개별 작업으로 구성해야 함&lt;/li&gt;
&lt;li&gt;각 작업은 시스템의 우선순위와 제약을 고려해 효율적으로 하나의 일을 처리해야 함&lt;/li&gt;
&lt;li&gt;cf) 아이폰에서 백그라운드 작업의 상태를 보려면 설정 &amp;gt; 배터리에서 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;1506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpasbq/btsPqTjndp4/oLaTaCfTLEnsk9YDSwrwW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpasbq/btsPqTjndp4/oLaTaCfTLEnsk9YDSwrwW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpasbq/btsPqTjndp4/oLaTaCfTLEnsk9YDSwrwW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdpasbq%2FbtsPqTjndp4%2FoLaTaCfTLEnsk9YDSwrwW0%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;1738&quot; height=&quot;1506&quot; data-origin-width=&quot;1738&quot; data-origin-height=&quot;1506&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅 글에서 계속..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://developer.apple.com/kr/videos/play/wwdc2025/227/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.apple.com/kr/videos/play/wwdc2025/227/&lt;/a&gt;&lt;/p&gt;</description>
      <category>WWDC 정리/WWDC 2025 정리</category>
      <category>bacgkround</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>wwdc2025</category>
      <category>wwdc25</category>
      <category>백그라운드</category>
      <category>백그라운드 앱</category>
      <author>jake-kim</author>
      <guid isPermaLink="true">https://ios-development.tistory.com/1807</guid>
      <comments>https://ios-development.tistory.com/1807#entry1807comment</comments>
      <pubDate>Wed, 23 Jul 2025 01:51:53 +0900</pubDate>
    </item>
  </channel>
</rss>