← 번역 목록으로

Blake Crosley · 2026년 4월 16일

AI 에이전트로 iOS 앱 만들기: 실무자 가이드

번역Blake Crosley원문 보기 ↗

AI 코딩 에이전트로 iOS 앱을 더 빠르게 출시하기. Claude Code, Codex CLI, Xcode 26.3 네이티브 에이전트 — MCP 설정, CLAUDE.md 패턴, hooks, 그리고 8개의 프로덕션 앱에서 얻은 솔직한 교훈.

words: 17231 read_time: 86m updated: 2026-04-16 00:00

TL;DR: 이제 세 가지 에이전트 런타임이 iOS 코드를 출시 단계까지 끌고 갈 수 있습니다. MCP를 사용하는 Claude Code CLI, MCP를 사용하는 Codex CLI, 그리고 Xcode 26.3의 네이티브 Intelligence 에이전트입니다. 두 개의 MCP 서버(59개 도구를 제공하는 XcodeBuildMCP와 20개 도구를 제공하는 Apple의 xcrun mcpbridge)는 에이전트에게 빌드, 테스트, 시뮬레이터, 디버깅에 대한 구조화된 접근 권한을 부여합니다. 이 가이드는 실제 CLAUDE.md 패턴, hook 구성, 그리고 무엇이 작동하고 무엇이 망가지는지에 대한 솔직한 평가를 다룹니다. 모두 총 293개의 Swift 파일로 구성된 8개의 프로덕션 iOS 앱에서 얻은 것입니다. 에이전트는 SwiftUI 뷰, SwiftData 모델, 리팩터링, 빌드 오류 진단에 탁월합니다. 그리고 .pbxproj 수정, 코드 사이닝, 시각적 디버깅에서 실패합니다. "에이전트가 Swift를 작성한다"와 "에이전트가 iOS 앱을 출시한다" 사이의 격차는 프롬프팅이 아니라 구성으로 메워집니다.

저는 AI 코딩 에이전트로 8개의 iOS 앱을 만들었습니다. 프로토타입이 아니라 — App Store에 올라간 앱들이며, HealthKit 통합, Metal 셰이더, SpriteKit 물리, iCloud 동기화, Live Activities, Game Center 리더보드, 그리고 iOS, watchOS, tvOS를 아우르는 멀티플랫폼 타겟까지 포함합니다. 이 앱들에 작성된 모든 Swift 코드는 에이전트가 작성하고 제가 검토했거나, 제가 작성하고 에이전트가 리팩터링했습니다. 제 추정으로는 그 비율이 대략 85/15로 에이전트 쪽에 기울어 있습니다.

이 가이드는 제가 시작할 때 있었으면 했던 레퍼런스입니다. 어떤 에이전트 런타임을 사용해야 하는지, 구조화된 빌드 접근을 위해 MCP 서버를 어떻게 구성하는지, CLAUDE.md에 무엇을 넣어야 하는지, 어떤 hook이 에이전트의 Xcode 프로젝트 파괴를 막아주는지, 그리고 — 결정적으로 — 에이전트가 어디서 실패하고 사람이 직접 운전대를 잡아야 하는지를 다룹니다.

핵심 요점

AI 에이전트가 처음인 iOS 개발자에게:

  • Claude Code CLI + XcodeBuildMCP로 시작하세요. 가장 성숙한 런타임이며 MCP 도구 커버리지가 가장 깊습니다. 명령어 두 개만 설치하고 프로젝트에 CLAUDE.md를 추가하면, 오류 메시지를 복사해서 붙여넣을 필요 없이 에이전트가 빌드, 테스트, 디버그를 할 수 있습니다.
  • 에이전트가 .pbxproj를 절대 수정하게 두지 마세요. 이 한 가지가 가장 중요한 규칙입니다. .pbxproj.xcodeproj/에 대한 쓰기를 차단하는 PreToolUse hook은 복구 작업에서 몇 시간을 아껴줍니다.
  • CLAUDE.md는 에이전트의 온보딩 문서입니다. CLAUDE.md에 1시간을 투자하면 에이전트의 실수를 바로잡는 10시간이 절약됩니다.

워크플로에 iOS를 추가하려는 숙련된 에이전트 사용자에게:

  • MCP는 iOS 빌드 루프를 변혁시킵니다. MCP 이전에는 에이전트가 Swift를 작성했지만 그것이 컴파일되는지 검증할 수 없었습니다. XcodeBuildMCP가 있으면, 에이전트가 코드를 작성하고, 빌드하고, 구조화된 오류를 읽고, 수정하고, 테스트를 실행합니다 — 자율적으로요.
  • 세 런타임은 서로 다른 필요를 충족합니다. 깊은 에이전틱 세션에는 Claude Code CLI, 헤드리스 배치 작업에는 Codex CLI, IDE를 떠나지 않고 빠르게 인라인 수정을 하려면 Xcode 26.3 네이티브 에이전트입니다.
  • Hook 인프라는 그대로 이어집니다. 기존의 PostToolUse 포매터, PreToolUse 차단기, 테스트 러너 hook은 약간의 경로 조정만으로 iOS 프로젝트에서도 동일하게 작동합니다.

AI 보조 iOS 개발을 평가하는 팀 리드에게:

  • 에이전트의 효율성은 프로젝트 규모가 아니라 프로젝트 문서화에 따라 확장됩니다. 잘 작성된 CLAUDE.md를 갖춘 63파일짜리 앱이 CLAUDE.md가 없는 14파일짜리 앱보다 더 좋은 에이전트 출력을 만들어냅니다.
  • .pbxproj 경계는 협상의 여지가 없습니다. 에이전트는 Xcode 프로젝트 파일을 안정적으로 편집할 수 없습니다. 워크플로에는 Xcode 타겟에 파일을 수동으로 추가하는 단계가 들어가야 합니다.
  • 솔직한 ROI: 에이전트는 구현 작업의 70~80%를 처리합니다. 나머지 20~30% — 시각적 마무리, 사이닝, 성능 튜닝, App Store 제출 — 에는 사람의 판단이 필요합니다.

경로 선택

필요한 것 | 가야 할 곳
---|---
처음으로 MCP 설정 | MCP 설정: 완전한 구성 — 두 서버를 설치, 검증, 에이전트 구성
iOS 프로젝트용 CLAUDE.md 작성 | iOS 프로젝트를 위한 CLAUDE.md 패턴 — 8개 앱의 실제 예시
세 가지 에이전트 런타임 비교 | iOS를 위한 세 가지 에이전트 런타임 — Claude Code 대 Codex 대 Xcode 네이티브
에이전트가 무엇을 할 수 있고 무엇을 할 수 없는지 이해 | 에이전트가 잘하는 일과 못하는 일
iOS 개발용 hook 설정 | iOS 개발을 위한 Hooks — format-on-save, .pbxproj 보호, 테스트 러너
심층 레퍼런스(이 페이지) | 계속 읽으세요 — 설정부터 고급 패턴까지 모든 것

이 가이드를 사용하는 방법

이 글은 3,000줄이 넘는 레퍼런스입니다. 본인의 경험 수준에 맞는 곳에서 시작하세요.

경험 | 시작 지점 | 그다음 탐색
---|---|---
iOS와 에이전트 둘 다 처음 | Prerequisites → MCP Setup → Your First Agent Session | CLAUDE.md Patterns, What Works/Doesn't
iOS 개발자, 에이전트는 처음 | Three Runtimes → MCP Setup → CLAUDE.md | Hooks, Architecture Patterns
에이전트 사용자, iOS는 처음 | Architecture Patterns → What Agents Do Poorly → CLAUDE.md | Framework-Specific Context, Advanced Workflows
둘 다 익숙함 | Advanced Workflows → Hooks → Multi-Platform Patterns | Runtime Comparison, The Portfolio

목차

  1. The Portfolio: 8 Apps, 293 Files
  2. Prerequisites
  3. Three Agent Runtimes for iOS
  4. MCP Setup: The Complete Configuration
  5. CLAUDE.md Patterns for iOS Projects
  6. Your First Agent Session
  7. What Agents Do Well in iOS
  8. What Agents Do Poorly in iOS
  9. Hooks for iOS Development
  10. Architecture Patterns That Work with Agents
  11. Framework-Specific Context
  12. Multi-Platform Patterns
  13. Advanced Workflows
  14. Real-World Case Studies
  15. Project Lifecycle with Agents
  16. Configuring Agent Definitions
  17. Testing Patterns for Agent-Assisted iOS
  18. Context Window Management for iOS Projects
  19. Troubleshooting
  20. Common Agent Mistakes in iOS
  21. The Honest Assessment
  22. FAQ
  23. Quick Reference Card
  24. References

관련 자료

주제 | 자료
---|---
Xcode를 위한 MCP 설정(짧은 블로그 포스트) | Two MCP Servers Made Claude Code an iOS Build System
Claude Code CLI 완전 레퍼런스 | Claude Code CLI: The Complete Guide
Codex CLI 레퍼런스 | Codex CLI: The Complete Guide
Hook 시스템 심층 분석 | Anatomy of a Claw: 84 Hooks as an Orchestration Layer
에이전트 아키텍처 패턴 | Agent Architecture Guide


포트폴리오: 8개 앱, 293개 파일

구성 이야기로 들어가기 전에, 이 가이드가 어디서 비롯되었는지부터 보겠습니다. 장난감 같은 프로젝트가 아닙니다 — 다섯 개의 Apple 프레임워크와 세 개의 플랫폼에 걸쳐 있고, 14파일짜리 운동 추적기부터 63파일짜리 멀티플랫폼 명상 타이머까지 iOS의 전 범위에 걸친 복잡도를 다룹니다.

앱 | 스택 | 파일 수 | 복잡도
---|---|---|---
Banana List | SwiftUI + SwiftData + iCloud Drive 동기화 + Claude Desktop을 위한 MCP 서버 | 53 | 풀 CRUD, iCloud 동기화, 앱 데이터를 Claude Desktop에 노출하는 커스텀 MCP 서버
Ace Citizenship | SwiftUI 학습 앱 + FastAPI 백엔드 | 26 | 클라이언트-서버, REST API 통합, 퀴즈 엔진
TappyColor | SpriteKit 색상 매칭 게임 | 30 | 게임 루프, 물리, 터치 처리, 파티클 효과
Return | 선(禪) 명상 타이머 — iOS 26+, watchOS, tvOS | 63 | HealthKit, Live Activities, Watch 확장 런타임, TV 포커스 내비게이션, iCloud 세션 동기화
amp97 | Metal 셰이더 + 오디오 시각화 | 41 | 커스텀 Metal 렌더 파이프라인, 오디오 분석, 실시간 GPU 컴퓨트
Reps | SwiftUI + SwiftData 운동 추적 | 14 | 최소 기능 앱, 깔끔한 SwiftData 패턴
Water | SwiftUI + SwiftData + Metal + HealthKit 수분 섭취 추적 | 34 | Metal 유체 시뮬레이션, HealthKit 음수량 기록, 위젯
Starfield Destroyer | SpriteKit + Metal 우주 슈터 | 32 | 99개 레벨, 8가지 기체, Game Center 리더보드, Metal 후처리

파일 수가 중요한 이유: 에이전트의 효율성은 프로젝트 크기가 아니라 프로젝트 가독성과 상관관계가 있습니다. Return(63파일)은 amp97(41파일)보다 더 좋은 에이전트 출력을 만들어내는데, Return에는 파일 주석, 아키텍처 다이어그램, 명시적인 패턴이 담긴 자세한 CLAUDE.md가 있기 때문입니다. amp97의 Metal 셰이더는 문서화 품질과 무관하게 본질적으로 에이전트가 추론하기 더 어렵습니다.


사전 준비물

iOS 개발용 에이전트 런타임을 설정하기 전에:

필수: - macOS 15+ (Sequoia) 또는 macOS Tahoe - Xcode 26.3+ 설치 및 구성(라이선스 동의 완료, 플랫폼 다운로드 완료) - 최소 한 개의 iOS Simulator 런타임 설치 - Anthropic API 계정(Claude Code용) 또는 OpenAI 계정(Codex용)

권장: - SwiftFormat 설치 (brew install swiftformat) — format-on-save hook에서 사용됨 - SwiftLint 설치 (brew install swiftlint) — 선택 사항이지만 스타일 강제에 유용함 - 터미널 사용 친숙도 — 세 런타임 모두 명령줄에서 작동하거나 명령줄과 통합됨

Xcode 설치 확인:



# Xcode 버전 확인
xcodebuild -version
# 기대값: Xcode 26.3 이상

# 사용 가능한 시뮬레이터 확인
xcrun simctl list devices available
# 기대값: 최소 한 개의 iPhone 시뮬레이터

# xcrun mcpbridge 사용 가능 여부 확인
xcrun mcpbridge --help
# 기대값: 사용법 정보(“command not found”가 아니어야 함)

xcrun mcpbridge가 "command not found"를 반환한다면 Xcode 26.3 이상이 필요합니다. App Store나 developer.apple.com을 통해 Xcode를 설치하거나 업데이트하세요. 참고: xcode-select --install은 Command Line Tools만 설치하며, 이는 mcpbridge를 포함하지 않습니다 — 전체 Xcode.app이 필요합니다.


iOS를 위한 세 가지 에이전트 런타임

세 가지 별개의 런타임이 iOS 코드를 작성하고, 빌드하고, 테스트할 수 있습니다. 이들은 서로 호환되는 대체재가 아닙니다 — 각각 다른 강점, 다른 MCP 통합 패턴, 다른 이상적인 사용 사례를 가집니다.

1. Claude Code CLI

무엇인가: Anthropic의 터미널 기반 에이전틱 코딩 어시스턴트. 코드베이스를 읽고, 명령어를 실행하고, 파일을 수정하고, MCP를 통해 외부 도구에 연결합니다.

MCP 통합: XcodeBuildMCP와 Apple의 Xcode MCP 모두 완전 지원. 에이전트는 MCP 프로토콜을 통해 도구를 발견하고 구조화된 매개변수로 도구를 호출합니다. 두 서버에 걸쳐 59 + 20개 도구.

설정:



# Claude Code 설치 (이미 설치되어 있지 않다면)
claude --version  # 설치 확인

# XcodeBuildMCP 추가 (59 도구 — 빌드, 테스트, 시뮬레이터, 디버깅)
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# Apple Xcode MCP 추가 (20 도구 — 파일 작업, 진단, Swift REPL, 미리보기)
claude mcp add --transport stdio xcode \
  -s user -- xcrun mcpbridge

최적 용도: 깊이 있는 구현 세션 — 새 기능 빌드, 여러 파일에 걸친 리팩터링, 복잡한 이슈 디버깅, 빌드-테스트-수정 루프 자율 실행. Claude Code의 1M 컨텍스트 윈도우(Opus 4.6)는 에이전트가 작업 메모리에 대부분의 작거나 중간 크기 iOS 프로젝트를 담을 수 있다는 뜻입니다 — 제 경험으로는 파일 크기에 따라 약 50개 파일까지 가능합니다.

전형적인 세션:



당신: 알림과 햅틱 피드백 토글이 있는 새 SettingsView를 추가해줘.
     TimerManager의 기존 Settings.swift 패턴을 사용해.
     구현 후 시뮬레이터용으로 빌드하고 오류는 수정해.

Claude: [Settings.swift, TimerManager.swift, 기존 뷰들을 읽음]
        [SettingsView.swift 생성]
        [MCP를 통해 build_sim 호출]
        [구조화된 오류 읽음: HealthKit import 누락]
        [import 수정]
        [build_sim 다시 호출 — 성공, 0 오류, 1 경고]
        [test_sim 호출 — 모든 테스트 통과]

MCP 이전 워크플로와의 핵심 차이점: 에이전트가 수동으로 빌드해 달라거나 오류 출력을 붙여 달라고 요청하지 않습니다. 빌드-오류-수정 루프가 자율적입니다.

2. Codex CLI

무엇인가: OpenAI의 터미널 기반 코딩 에이전트. 개념적으로 Claude Code와 비슷하지만 OpenAI 모델(GPT-4o, o3)을 사용하며 권한 모델이 다릅니다.

MCP 통합: Codex는 codex mcp add 명령어를 통해 MCP를 지원합니다. Apple의 Xcode MCP가 직접 작동합니다:



# Codex에 Apple Xcode MCP 추가
codex mcp add xcode -- xcrun mcpbridge

XcodeBuildMCP도 동일한 npx 명령어를 통해 Codex와 작동합니다:



# Codex에 XcodeBuildMCP 추가
codex mcp add XcodeBuildMCP -- npx -y xcodebuildmcp@latest mcp

최적 용도: 헤드리스 배치 작업, CI/CD 통합, 그리고 다른 모델 군에서 두 번째 의견을 받고 싶은 작업. Codex의 샌드박스 모드는 격리된 환경에서 코드를 실행하므로, 상태를 변경하는 테스트 스위트 실행 같은 파괴적 작업에 유용합니다.

Claude Code와의 핵심 차이점: - Claude 모델 대신 OpenAI 모델 사용 - 다른 컨텍스트 윈도우 크기와 토큰 경제 - 샌드박스 우선 권한 모델(기본적으로 더 제한적) - 더 작은 MCP 생태계(테스트된 커뮤니티 서버 수가 더 적음) - Hooks 시스템 사용 가능(v0.119.0+) 하지만 Claude Code 것보다 덜 성숙함 — 이벤트 타입이 적고 조건부 if 필드 없음

iOS에서 Claude Code 대신 Codex를 사용해야 할 때:

모델 다양성을 원할 때 Codex를 사용하세요 — 첫 번째 에이전트가 작성한 코드를 두 번째 에이전트가 검토하면 다른 종류의 오류가 잡힙니다. collab 워크플로(Claude가 빌드, Codex가 검토)는 iOS에서 효과적입니다. 한 모델 군에는 옳아 보이는 SwiftUI 패턴이 다른 모델 군이 잡아내는 미묘한 이슈를 가질 수 있기 때문입니다. Metal 셰이더와 동시성 패턴은 특히 듀얼 모델 검토에서 이득을 봅니다.

3. Xcode 26.3 네이티브 에이전트

무엇인가: Apple은 Xcode의 Intelligence 패널에 AI 코딩 에이전트를 직접 통합했습니다. Xcode 26.3 기준으로, Xcode Settings > Intelligence에서 Claude Agent와 Codex를 인텔리전스 제공자로 구성할 수 있습니다.

설정:

  1. Xcode 26.3+ 열기
  2. Settings > Intelligence로 이동
  3. 새 제공자 추가:
  4. Claude의 경우: "Claude Agent" 선택, Anthropic API 키 입력
  5. Codex의 경우: "Codex" 선택, OpenAI API 키 입력
  6. 에이전트가 Intelligence 사이드바에 나타나며 인라인으로 호출 가능

최적 용도: 빠른 인라인 편집, 에이전트 수준의 추론을 갖춘 코드 자동 완성, 그리고 Xcode를 떠나는 것을 싫어하는 개발자. 네이티브 통합은 에이전트가 MCP 브리징 없이 Xcode의 프로젝트 컨텍스트(열린 파일, 빌드 타겟, scheme 구성)에 직접 접근한다는 뜻입니다.

CLI 에이전트 대비 한계: - hook 시스템 없음 — format-on-save를 강제하거나 .pbxproj 쓰기를 차단할 수 없음 - CLAUDE.md 로드 없음 — 에이전트가 프로젝트 수준 구성 파일을 읽지 않음 - 제한된 자율성 — 에이전트는 현재 파일이나 선택 영역에서 작동하며 프로젝트 전체에서 작동하지 않음 - 서브에이전트 위임 없음 — 복잡한 다단계 작업을 병렬화할 수 없음 - MCP 서버 구성 없음 — 에이전트는 Xcode의 내장 도구만 사용

Xcode 네이티브 에이전트를 사용해야 할 때:

빠르고 범위가 좁은 편집에서 터미널로 전환하는 것이 오버헤드일 때 사용합니다. "이 모델에 computed property를 추가해줘." "이 함수에 대한 단위 테스트를 작성해줘." "이 뷰를 @Observable을 사용하도록 리팩터링해줘." 한두 파일만 건드리고 빌드-테스트 사이클이 필요 없는 작업입니다.

빌드, 테스트, 멀티 파일 리팩터링, 또는 자율 오류 수정이 필요한 모든 것에는 MCP를 갖춘 CLI 에이전트를 사용하세요.

런타임 비교 매트릭스

기능 | Claude Code CLI | Codex CLI | Xcode 26.3 네이티브
---|---|---|---
MCP 지원 | 완전 (79 도구) | 완전 (79 도구) | 내장 Xcode 도구만
Hook 시스템 | 예 (성숙) | 예 (기본, v0.119.0+) | 아니오
CLAUDE.md / 프로젝트 구성 | 예 | codex.md 동등물 | 아니오
자율 빌드-테스트-수정 | 예 (MCP 경유) | 예 (MCP 경유) | 부분적 (인라인만)
서브에이전트 위임 | 예 (최대 10개 병렬) | 아니오 | 아니오
컨텍스트 윈도우 | 1M 토큰 (Opus 4.7 / 4.6, 표준 가격) | 모델별로 다름 | 제공자별로 다름
다중 파일 작업 | 코드베이스 전체 접근 | 코드베이스 전체 접근 | 현재 파일 / 선택 영역
.pbxproj 보호 | hook 경유 | 수동 | 해당 없음 (Xcode 네이티브 사용)
저장 시 포맷 | PostToolUse hook 경유 | 외부 도구 | Xcode 설정
오프라인 기능 | 아니오 | 아니오 | 아니오
비용 모델 | Anthropic API 사용 | OpenAI API 사용 | 제공자 API 사용

권장 사항: Claude Code CLI를 주 런타임으로 사용하세요. 빠른 인라인 편집에는 Xcode 26.3 네이티브 에이전트를 사용하세요. 검토 패스와 배치 작업에는 Codex CLI를 사용하세요. 셋은 경쟁이 아니라 보완 관계입니다.


MCP 설정: 완전한 구성

MCP(Model Context Protocol)는 에이전트를 "Swift를 작성하고 당신이 빌드해 주기를 바라는" 상태에서 "Swift를 작성하고, 빌드하고, 구조화된 오류를 읽고, 수정하는" 상태로 변환시키는 것입니다. 이 절은 블로그 포스트보다 더 깊이 들어갑니다 — 두 서버, 모든 설치 방법, 검증, 그리고 도구가 실제로 사용되도록 보장하는 에이전트 구성을 다룹니다.

XcodeBuildMCP: 헤드리스 iOS 개발을 위한 59개 도구

XcodeBuildMCPxcodebuild, xcrun simctl, LLDB를 59개의 구조화된 MCP 도구로 감쌉니다. Xcode가 실행되지 않아도 작동합니다 — 빌드-테스트-디버그 사이클 전체가 Apple의 명령줄 도구를 통해 헤드리스로 동작합니다.

설치 옵션:



# 옵션 1: npx 경유 (권장 — 항상 최신 버전 사용)
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# 옵션 2: Homebrew 경유 (버전 고정, 수동 업데이트)
brew install xcodebuildmcp
claude mcp add XcodeBuildMCP \
  -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- xcodebuildmcp mcp

# 옵션 3: 프로젝트 범위 (-s user 생략)
claude mcp add XcodeBuildMCP \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

-s user 플래그는 서버를 모든 프로젝트에서 전역으로 사용할 수 있게 해줍니다. 프로젝트 범위 설치를 원할 때는 생략합니다(웹 프로젝트가 아니라 iOS 프로젝트에만 MCP가 필요할 때 유용).

-e XCODEBUILDMCP_SENTRY_DISABLED=true 환경 변수는 충돌 보고 텔레메트리를 비활성화합니다. XcodeBuildMCP는 기본적으로 Sentry를 포함하는데, 이는 파일 경로를 비롯한 오류 데이터를 전송합니다. 프로젝트에 진단 데이터를 기여하고 싶지 않다면 옵트아웃하세요.

전체 도구 목록(8개 카테고리에 걸쳐 59개 도구):

카테고리 | 도구 | 하는 일
---|---|---
프로젝트 발견 | discover_projs, list_schemes, list_targets | .xcodeproj/.xcworkspace 파일 찾기, 사용 가능한 scheme과 target 나열
빌드 | build_sim, build_device, build_mac | 파일과 줄별로 분류된 구조화된 JSON 오류/경고 출력으로 빌드
테스트 | test_sim, test_device | 메서드별 통과/실패 결과로 테스트 실행
시뮬레이터 라이프사이클 | list_sims, boot_sim, shutdown_sim, open_sim, session_set_defaults | 시뮬레이터 생성, 부팅, 관리, 구성
디바이스 관리 | list_devices, install_device, launch_device | 실제 디바이스 배포 및 관리
디버깅 | debug_attach_sim, debug_attach_device, debug_breakpoint, debug_stack, debug_variables, debug_eval, debug_continue, debug_step, debug_detach | 중단점과 변수 검사가 포함된 LLDB 완전 통합
UI 자동화 | snapshot_ui, screenshot, tap, swipe, type_text | 자동화된 상호작용 및 시각적 캡처
프로젝트 스캐폴딩 | create_project, add_file, add_package | 프로젝트 생성 및 의존성 추가

일상 작업에서 가장 중요한 도구들:

  1. build_sim — 이걸 수백 번 호출하게 됩니다. 파일, 줄, 심각도별로 분류된 오류를 JSON으로 반환합니다. 에이전트가 오류를 읽고, 파일로 이동해, 당신이 아무것도 건드리지 않은 상태에서 수정합니다.

  2. test_sim — 테스트 메서드별 결과를 반환합니다. 에이전트는 "테스트 실패"가 아니라 어떤 테스트가 왜 실패했는지를 정확히 압니다.

  3. list_sims + boot_simxcrun simctl 플래그를 외울 필요 없는 시뮬레이터 관리. 에이전트가 사용 가능한 런타임을 발견하고 적절한 디바이스를 고릅니다.

  4. discover_projs + list_schemes — 프로젝트 인트로스펙션. 에이전트가 scheme 이름이나 워크스페이스 구조를 추측할 필요가 없습니다.

  5. debug_attach_sim + debug_stack + debug_variables — 원격 LLDB 디버깅. 에이전트가 디버거를 직접 열지 않고도 중단점을 설정하고, 변수를 검사하고, 코드를 단계 실행할 수 있습니다.

Apple Xcode MCP: Xcode와 연결하는 20개 도구

Apple의 MCP 서버는 Xcode 26.3에 xcrun mcpbridge로 함께 제공됩니다. 실행 중인 Xcode 프로세스와 XPC(Apple의 프로세스 간 통신 프레임워크)를 통해 통신하며, 다른 어떤 CLI 도구로도 접근할 수 없는 내부 상태를 노출합니다.

설치:



# 표준 설치 (전역)
claude mcp add --transport stdio xcode \
  -s user -- xcrun mcpbridge

# Codex CLI용
codex mcp add xcode -- xcrun mcpbridge

Xcode 26.3+ 와 실행 중인 Xcode 프로세스가 필요합니다. Xcode가 열려 있지 않으면 이 서버를 통한 모든 MCP 호출은 실패하거나 멈춥니다. XcodeBuildMCP에는 이 제한이 없습니다.

도구 목록(5개 카테고리에 걸쳐 20개 도구):

카테고리 | 도구 | 하는 일
---|---|---
파일 작업 | XcodeRead, XcodeWrite, XcodeUpdate, XcodeGlob, XcodeGrep | Xcode 프로젝트 컨텍스트 안에서 파일 읽기/쓰기
빌드 & 테스트 | BuildProject, GetBuildLog, RunAllTests, RunSomeTests | Xcode 내부 빌드 시스템으로 빌드 및 테스트
진단 | XcodeListNavigatorIssues, XcodeRefreshCodeIssuesInFile | 실시간 코드 진단(빌드 오류뿐 아니라)
코드 & 문서 | ExecuteSnippet, DocumentationSearch | Swift REPL 실행 및 Apple 문서 검색
미리보기 | RenderPreview | 헤드리스 SwiftUI 미리보기 렌더링

Apple MCP에만 있는 고유 도구(XcodeBuildMCP에는 없음):

  1. DocumentationSearch — WWDC 세션을 포함한 Apple 개발자 문서를 검색합니다. Apple API 질문에는 웹 검색보다 빠르고 신뢰할 수 있습니다. "HKQuantityType(.dietaryWater)이 유효한가?"라고 묻고 원천에서 확정적인 답을 받으세요.

  2. ExecuteSnippet — 프로젝트 컨텍스트 내의 Swift REPL 실행. 에이전트가 전체 앱을 빌드하지 않고도 API 동작을 확인하고, 타입 변환을 테스트하고, 표현식을 검증할 수 있습니다.

  3. RenderPreview — SwiftUI 미리보기를 헤드리스로 렌더링합니다. 에이전트가 뷰가 오류 없이 렌더링되는지 확인할 수 있지만, 시각적 정확성은 평가할 수 없습니다(렌더는 시각적으로 검사되는 것이 아니라 데이터로 반환됨).

  4. XcodeListNavigatorIssues — Xcode 분석기의 실시간 진단을 반환합니다. 빌드 오류뿐 아니라 미사용 변수, 잠재적 retain cycle, 빌드 시스템이 드러내지 않는 deprecation 경고 같은 이슈를 잡아냅니다.

두 서버 모두를 사용하는 이유

빌드와 테스트에서는 겹치지만 근본적으로 다릅니다:



┌─────────────────────────────────────────────────────────────────┐
│                     MCP TOOL COVERAGE                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  XcodeBuildMCP (59 tools)        Apple Xcode MCP (20 tools)    │
│  ┌─────────────────────┐         ┌─────────────────────┐       │
│  │ Standalone           │         │ Requires Xcode      │       │
│  │ (no Xcode process)  │         │ (XPC bridge)        │       │
│  │                     │         │                     │       │
│  │ ✓ Simulators        │  BOTH   │ ✓ Documentation     │       │
│  │ ✓ Real devices      │ ┌─────┐ │ ✓ Swift REPL        │       │
│  │ ✓ LLDB debugging    │ │Build│ │ ✓ SwiftUI previews  │       │
│  │ ✓ UI automation     │ │Test │ │ ✓ Live diagnostics  │       │
│  │ ✓ Project scaffold  │ └─────┘ │ ✓ Analyzer issues   │       │
│  │ ✓ Screenshot        │         │                     │       │
│  └─────────────────────┘         └─────────────────────┘       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

XcodeBuildMCP를 사용해야 하는 곳: 빌드-테스트-디버그 사이클. Xcode가 열려 있지 않아도 작동하고, 시스템 메모리를 덜 소비하며, 더 풍부한 시뮬레이터 및 디바이스 관리를 제공합니다. 이것이 주 빌드 도구입니다.

Apple Xcode MCP를 사용해야 하는 곳: 문서 조회, Swift REPL 검증, SwiftUI 미리보기 렌더링, 실시간 진단. 이런 기능이 필요한 세션 동안 Xcode를 열어 두세요.

실무에서: 저는 MCP 호출의 약 90%를 XcodeBuildMCP로 하고, 문서와 REPL 검증은 Apple Xcode MCP를 씁니다. 에이전트는 빌드와 테스트에 기본적으로 XcodeBuildMCP를 씁니다. 더 빠르고(Xcode 프로세스 오버헤드 없음) 더 안정적이기 때문입니다(XPC 의존 없음).

검증

두 서버를 설치한 후 연결되었는지 확인합니다:



# 구성된 MCP 서버 모두 나열
claude mcp list

# 기대 출력에 다음이 포함되어야 함:
# XcodeBuildMCP: npx -y xcodebuildmcp@latest mcp - Connected
# xcode: xcrun mcpbridge - Connected

서버가 "Disconnected"로 표시되거나 나타나지 않으면:

  1. XcodeBuildMCP가 연결되지 않음: Node.js가 설치되어 있는지 확인하세요(node --version). npx 명령은 Node.js 18+이 필요합니다.
  2. Apple Xcode MCP가 연결되지 않음: Xcode 26.3+가 설치되어 있고 터미널에서 xcrun mcpbridge 명령이 작동하는지 확인하세요. 라이선스 동의를 위해 Xcode를 한 번 이상 열어야 합니다.
  3. 둘 다 나타나지 않음: Claude Code를 재시작하세요(새 터미널에서 claude). 세션 도중 등록된 MCP 서버는 재시작 전까지 나타나지 않을 수 있습니다.

에이전트가 MCP를 사용하도록 가르치기

MCP 서버 설치는 필요하지만 충분하지 않습니다. 명시적인 안내 없이는 에이전트가 Bash로 xcodebuild를 실행하거나(비구조화 출력, 컨텍스트 토큰 낭비) Apple 문서를 위해 웹 검색을 사용하는(더 느리고 덜 안정적) 식으로 후퇴할 수 있습니다.

CLAUDE.md나 에이전트 정의에 다음을 추가하세요:



## Build & Test — Always Use MCP

Prefer MCP tools over raw shell commands for ALL build operations:

- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim` (NOT `xcrun simctl` via Bash)
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)
- **Previews**: `RenderPreview` for headless SwiftUI verification

MCP returns structured JSON. Bash returns unstructured text.
Structured data means fewer tokens consumed and better error diagnosis.

이 안내는 에이전트가 MCP 도구를 먼저 손에 잡도록 보장합니다. 이게 없으면 에이전트가 Bash로 긴 xcodebuild 명령을 구성하고, 출력을 파싱하느라 수천 컨텍스트 토큰을 소비하며, 가끔 실제 오류를 잘못 식별하는 모습을 보게 될 것입니다.


iOS 프로젝트를 위한 CLAUDE.md 패턴

CLAUDE.md는 에이전트 보조 개발에서 프로젝트 안에서 가장 중요한 파일입니다. 에이전트의 온보딩 문서이며 — 아키텍처 문서를 읽은 신입과 추측만 하는 신입 사이의 차이를 만듭니다.

제가 유지하는 모든 iOS 프로젝트에는 CLAUDE.md가 있습니다. 8개 앱 모두에서 도출된, 효과 있는 패턴들을 소개합니다.

필수 섹션

모든 iOS CLAUDE.md에는 이 여섯 섹션이 필요합니다. 나머지는 모두 선택입니다.

1. 프로젝트 정체성



# Return - Zen Focus Timer

**Bundle ID:** `com.941apps.Return`
**Target:** iOS 26+ / macOS Tahoe / watchOS 26+ / tvOS 26+
**Architecture:** SwiftUI with @Observable pattern, companion Watch and TV apps
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0

이게 중요한 이유: 에이전트는 코드를 작성하기 전에 배포 타겟을 알아야 합니다. iOS 17을 타겟으로 하는 에이전트는 NavigationView@ObservedObject를 사용할 것입니다. iOS 26을 타겟으로 하는 에이전트는 NavigationStack@Observable을 사용할 것입니다. 번들 ID는 entitlement와 HealthKit 구성에 중요합니다. Swift 버전은 동시성 모델(async/await 대 completion handler, strict concurrency 대 lenient)을 결정합니다.

2. 목적 주석이 달린 파일 구조



## File Structure

Return/
├── ReturnApp.swift           # 앱 진입점, 다크 모드 강제
├── ContentView.swift         # 테마 배경이 적용된 메인 타이머 뷰
├── TimerManager.swift        # 타이머 상태, 로직, 반복 처리
├── AudioManager.swift        # AVAudioPlayer로 사운드 재생
├── Settings.swift            # 검증을 동반한 중앙 집중형 설정
├── SettingsSheet.swift       # 설정 UI
├── HealthKitManager.swift    # 마음챙김 세션 로깅 + 디바이스 간 동기화
├── LiveActivityManager.swift # 잠금 화면/Dynamic Island
├── Theme.swift               # 테마 정의
├── ThemeManager.swift        # 테마 상태 관리
├── VideoBackgroundView.swift # AVPlayer 동영상 배경
├── GlassTextShape.swift      # 글래스 효과를 위한 Core Text 글리프 경로
├── GlassTimerText.swift      # 글래스 머티리얼이 적용된 타이머 텍스트
└── Constants.swift           # 앱 상수

각 파일명 뒤의 인라인 주석은 장식이 아닙니다. 작성할 수 있는 단일 문서로서 가장 레버리지가 큰 문서화입니다. 에이전트가 어디에 새 기능을 추가할지 결정할 때, 이 주석들이 프로젝트 레이아웃을 이해하기 위해 모든 파일을 읽는 대신 첫 시도에서 올바른 파일로 안내합니다.

안티패턴: 주석 없이 파일만 나열하는 것. TimerManager.swift는 그것이 상태를, UI를, 또는 둘 다를 처리하는지 에이전트에게 아무것도 알려주지 않습니다. TimerManager.swift # Timer state, logic, and repeat handling은 거기에 무엇이 들어가야 하고 무엇은 들어가면 안 되는지 정확히 알려줍니다.

3. 빌드와 테스트 명령



## Build & Test

iOS 시뮬레이터용 빌드:
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build

테스트 실행:
xcodebuild -scheme Return -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test

tvOS 테스트 실행:
xcodebuild -scheme ReturnTV -destination 'platform=tvOS Simulator,name=Apple TV' test

**MCP 도구를 선호** (`build_sim`, `test_sim`) — 위 raw 명령보다. MCP는 카테고리화된 오류가 담긴 구조화된 JSON을 반환합니다.

에이전트가 MCP를 선호해야 하더라도 raw 명령을 포함하세요. raw 명령은 폴백 문서 역할을 하며 scheme 이름과 destination을 명시화합니다.

4. 핵심 패턴과 규칙



## Key Patterns

### Observable Architecture
- ALL view models use `@Observable` (NEVER `ObservableObject`)
- ALL navigation uses `NavigationStack` (NEVER `NavigationView`)
- State management via `@Observable` classes with `@MainActor` isolation

### Settings Pattern
- Centralized `Settings.shared` singleton
- All settings bounded to valid ranges with validation
- Sound names validated against whitelist
- Thread-safe access via @MainActor

### Audio System
- `AVAudioPlayer` with `.playback` category (plays in silent mode)
- Silent audio loop for background execution
- Bell playback with completion callbacks and token-based staleness

이 패턴은 에이전트가 일관성 없는 코드를 도입하는 것을 막습니다. 명시적인 패턴 문서가 없으면 에이전트는 한 파일에서는 ObservableObject를, 다른 파일에서는 @Observable을 쓰거나, 기존 Settings.shared 싱글톤을 쓰는 대신 새 설정 메커니즘을 만들어내곤 합니다.

5. 에이전트가 절대 해서는 안 되는 일들



## Rules

- **NEVER modify .pbxproj files** — create Swift files, then I will add them to Xcode manually
- **NEVER modify .xcodeproj/ contents directly**
- **NEVER add new package dependencies** without asking first
- **NEVER change the deployment target**
- **NEVER modify entitlements files** unless explicitly asked
- **NEVER use NavigationView** — always NavigationStack
- **NEVER use ObservableObject** — always @Observable
- **NEVER use @StateObject** — always @State with @Observable

명시적 금지가 암묵적 기대보다 더 효과적입니다. 에이전트는 부정 제약(하라/하지 마라)이 휴리스틱(이걸 선호하라/가끔 저걸 써라)보다 더 신뢰성 있게 따릅니다. 부정 제약이 이진적이기 때문입니다.

6. 프레임워크별 컨텍스트

이 절은 앱마다 다릅니다. 비자명한 구성을 가진 모든 프레임워크에 대해 포함하세요:

HealthKit 앱의 경우:



## HealthKit Configuration

- Entitlement: `com.apple.developer.healthkit`
- Info.plist keys:
  - `NSHealthShareUsageDescription`: "Return reads your mindful minutes..."
  - `NSHealthUpdateUsageDescription`: "Return logs meditation sessions..."
- Category types: `HKCategoryType(.mindfulSession)`
- Authorization checked on every write (user can revoke at any time)
- HealthKit is unavailable on tvOS — guard with `#if canImport(HealthKit)`

SwiftData 앱의 경우:



## SwiftData Models

### Model Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList`
- `GroceryItem` has optional `Category`

### Model Container Setup
- Configured in App struct with `modelContainer(for:)`
- Schema versioning: currently V2
- Migration plan: `GroceryMigrationPlan` handles V1 → V2

### Queries
- `@Query(sort: \GroceryItem.name)` for sorted fetches
- `@Query(filter: #Predicate { !$0.isCompleted })` for active items
- Always use `@Query` in views, `modelContext.fetch()` in managers

SpriteKit 앱의 경우:



## SpriteKit Scene Hierarchy

GameScene (SKScene)
├── backgroundLayer (SKNode, zPosition: -100)
│   └── StarfieldNode (custom, parallax scrolling)
├── gameLayer (SKNode, zPosition: 0)
│   ├── playerShip (PlayerNode, zPosition: 10)
│   ├── enemyContainer (SKNode, zPosition: 5)
│   └── bulletPool (SKNode, zPosition: 8)
├── effectsLayer (SKNode, zPosition: 50)
│   └── ParticleManager (manages explosion/trail emitters)
└── hudLayer (SKNode, zPosition: 100)
    ├── scoreLabel (SKLabelNode)
    └── healthBar (HealthBarNode)

- Physics categories defined in `PhysicsCategory.swift` as bitmasks
- Contact detection via `didBegin(_ contact:)` on GameScene
- Bullet pooling: pre-allocate 50, recycle via `removeFromParent()` + re-add

Metal 앱의 경우:



## Metal Pipeline

- Render pipeline: `MetalView` → `Renderer` → `ShaderLibrary`
- Compute pipeline: `AudioAnalyzer` → compute shader → texture output
- Shared uniforms struct: `Uniforms` in `ShaderTypes.h` (bridged to Swift)
- Frame timing: `CADisplayLink` drives render loop
- Buffer triple-buffering: 3 in-flight frames with semaphore

### Shader Files
- `Shaders.metal` — Main render shaders (vertex + fragment)
- `Compute.metal` — Audio analysis compute kernel
- `PostProcess.metal` — Bloom and color grading

### DO NOT modify Metal shaders without testing on device.
Simulator Metal is not representative of device GPU behavior.

실제 CLAUDE.md: Banana List (SwiftUI + SwiftData + iCloud + MCP 서버)

여기 여섯 섹션이 어떻게 함께 작동하는지 보여주는, 적당히 복잡한 앱의 주석 달린 예시가 있습니다. iCloud 동기화와 앱 데이터를 Claude Desktop에 노출하는 커스텀 MCP 서버를 갖춘 53파일짜리 식료품 리스트 앱 Banana List에 대해 제가 사용하는 CLAUDE.md 패턴입니다:



# Banana List - Grocery List App

**Bundle ID:** `com.941apps.BananaList`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData + iCloud Drive sync
**Swift version:** 6.2
**Minimum deployment:** iOS 26.0

## Core Features

- Grocery lists with items, categories, and quantities
- iCloud Drive sync via SwiftData CloudKit integration
- Custom MCP server exposing list data to Claude Desktop
- Liquid Glass design system
- Haptic feedback on interactions
- Share sheets for list sharing

## File Structure

BananaList/
├── BananaListApp.swift       # 앱 진입점, 모델 컨테이너 설정
├── Models/
│   ├── GroceryList.swift     # @Model: 이름, 항목, 색상이 있는 리스트
│   ├── GroceryItem.swift     # @Model: 이름, 수량, 카테고리, isCompleted를 가진 항목
│   ├── Category.swift        # @Model: 사용자 정의 카테고리
│   └── SampleData.swift      # 미리보기 및 테스트 데이터
├── Views/
│   ├── ListsView.swift       # 메인 리스트 화면
│   ├── ListDetailView.swift  # 리스트 내부 항목들
│   ├── ItemRow.swift         # 스와이프 액션이 있는 단일 항목 행
│   ├── AddItemSheet.swift    # 새 항목 폼
│   ├── CategoryPicker.swift  # 새로 만들기 기능이 있는 카테고리 선택기
│   └── SettingsView.swift    # 앱 설정
├── Managers/
│   ├── CloudSyncManager.swift # iCloud Drive 동기화 상태와 충돌 해결
│   └── HapticManager.swift   # UIImpactFeedbackGenerator 래퍼
├── MCP/
│   ├── MCPServer.swift       # Claude Desktop 통합용 MCP 서버
│   ├── ListTools.swift       # MCP 도구: 리스트 CRUD
│   └── ItemTools.swift       # MCP 도구: 항목 CRUD
└── Extensions/
    ├── Color+Extensions.swift # 커스텀 컬러 정의
    └── View+Extensions.swift  # 재사용 가능한 view modifier

## SwiftData Models

### Relationships
- `GroceryList` has many `GroceryItem` (cascade delete)
- `GroceryItem` belongs to one `GroceryList` (required)
- `GroceryItem` has optional `Category`
- `Category` has many `GroceryItem` (nullify on delete)

### Container Setup
@main
struct BananaListApp: App {
    var body: some Scene {
        WindowGroup {
            ListsView()
        }
        .modelContainer(for: [GroceryList.self, GroceryItem.self, Category.self])
    }
}

### Query Patterns
- Lists: `@Query(sort: \GroceryList.name) var lists: [GroceryList]`
- Active items: `@Query(filter: #Predicate { !$0.isCompleted })`
- By category: filter in-memory after fetch (SwiftData predicate limitations)

## Build & Test

xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme BananaList -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test

Prefer MCP tools (`build_sim`, `test_sim`) over raw commands.

## Key Patterns

### Observable + SwiftData
- SwiftData `@Model` classes are automatically Observable
- DO NOT add `@Observable` to `@Model` classes (redundant, causes warnings)
- Use `@Bindable` for two-way bindings to model properties in forms
- Use `@Query` in views, `modelContext.fetch()` in non-view code

### iCloud Sync
- Automatic via SwiftData CloudKit integration
- Conflict resolution: last-write-wins (CloudKit default)
- Sync status exposed via `CloudSyncManager.shared.syncState`
- Test sync by running on two simulators with same iCloud account

### MCP Server Architecture
- Runs as a local WebSocket server on port 8765
- Exposes 6 tools: listAll, getList, createList, addItem, completeItem, deleteItem
- Claude Desktop connects via MCP config in `~/.config/claude-desktop/config.json`

## Rules

- NEVER modify .pbxproj or .xcodeproj contents
- NEVER change the model schema without updating SampleData.swift
- NEVER use `ObservableObject` — SwiftData models are already Observable
- NEVER use `@StateObject` — use `@State` with `@Observable` classes
- NEVER use `NavigationView` — always `NavigationStack`
- NEVER add `@Observable` macro to `@Model` classes
- ALWAYS use `@Bindable` for form bindings to model properties
- ALWAYS test iCloud sync changes on two simulator instances

실제 CLAUDE.md: Reps (최소 SwiftData 앱 — 14 파일)

작은 프로젝트에서는 CLAUDE.md를 간결하게 유지할 수 있습니다. 14파일짜리 운동 추적기 Reps의 패턴입니다. 짧은 CLAUDE.md조차 여섯 가지 핵심 섹션을 모두 담고 있다는 점을 주목하세요:



# Reps - Workout Tracking

**Bundle ID:** `com.941apps.Reps`
**Target:** iOS 26+
**Architecture:** SwiftUI + SwiftData
**Swift version:** 6.2

## File Structure

Reps/
├── RepsApp.swift                # 앱 진입점, 모델 컨테이너
├── Models/
│   ├── Workout.swift            # @Model: 운동, 날짜, 시간을 가진 워크아웃
│   ├── Exercise.swift           # @Model: 세트, 반복 수, 무게가 있는 운동
│   └── ExerciseTemplate.swift   # @Model: 저장된 운동 정의
├── Views/
│   ├── WorkoutListView.swift    # 워크아웃 메인 리스트
│   ├── WorkoutDetailView.swift  # 워크아웃 내 운동들
│   ├── ExerciseRow.swift        # 인라인 편집이 가능한 단일 운동
│   ├── AddExerciseSheet.swift   # 템플릿에서 운동 선택
│   ├── NewWorkoutView.swift     # 새 워크아웃 시작 흐름
│   └── StatsView.swift          # 진행 차트와 요약
├── Managers/
│   └── WorkoutTimer.swift       # 활성 워크아웃 타이머
└── Extensions/
    └── Date+Extensions.swift    # 포맷 헬퍼

## Build & Test

xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme Reps -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test

## SwiftData Relationships

- `Workout` has many `Exercise` (cascade delete)
- `Exercise` has optional `ExerciseTemplate`
- `ExerciseTemplate` standalone (nullify on exercise delete)

## Rules

- NEVER modify .pbxproj
- NEVER use ObservableObject — use @Observable
- NEVER use NavigationView — use NavigationStack
- @Model classes are already Observable — do not add @Observable macro
- Use @Bindable for form bindings to model properties

이건 14파일짜리 프로젝트에 40줄짜리 CLAUDE.md입니다. 작성에 10분이 걸리고 에이전트 혼란 시간으로 따지면 몇 시간을 절약합니다.

실제 CLAUDE.md: Starfield Destroyer (SpriteKit + Metal — 32 파일)

게임 프로젝트는 더 많은 프레임워크별 컨텍스트를 요구합니다. 에이전트는 씬 그래프, 물리 카테고리, 게임 상태 머신을 이해해야 합니다:



# Starfield Destroyer - Space Shooter

**Bundle ID:** `com.941apps.StarfieldDestroyer`
**Target:** iOS 26+
**Architecture:** SpriteKit + Metal post-processing + Game Center
**Swift version:** 6.2

## Game Overview

99 levels across 3 galaxies. 8 unlockable ships with different stats.
Game Center leaderboards and achievements. Metal shader post-processing
for bloom and screen effects.

## File Structure

StarfieldDestroyer/
├── StarfieldDestroyerApp.swift  # 앱 진입점, Game Center 인증
├── GameScene.swift              # 메인 게임 씬, 업데이트 루프
├── MenuScene.swift              # 타이틀 화면, 함선 선택
├── Entities/
│   ├── PlayerShip.swift         # 물리, 무기, 실드를 가진 플레이어 노드
│   ├── EnemyShip.swift          # AI 행동을 가진 적 기본 클래스
│   ├── Bullet.swift             # 총알 풀 노드
│   ├── PowerUp.swift            # 수집 가능한 파워업
│   └── Boss.swift               # 보스 적 (33, 66, 99 레벨)
├── Systems/
│   ├── LevelManager.swift       # 레벨 진행, 웨이브 스폰
│   ├── PhysicsCategory.swift    # UInt32 비트마스크 카테고리
│   ├── CollisionHandler.swift   # 컨택트 델리게이트 메서드
│   ├── ScoreManager.swift       # 스코어 추적, 멀티플라이어
│   ├── ParticleManager.swift    # 폭발, 트레일, 실드 이미터
│   └── AudioManager.swift       # 효과음, 배경음
├── UI/
│   ├── HUDNode.swift            # 스코어, 체력, 레벨 표시
│   ├── ShipSelectView.swift     # SwiftUI 함선 선택 (UIHostingController)
│   ├── GameOverView.swift       # 스코어 제출이 있는 게임 오버 화면
│   └── PauseMenu.swift          # 일시정지 오버레이
├── Metal/
│   ├── MetalRenderer.swift      # 후처리 렌더 파이프라인
│   ├── BloomShader.metal        # Bloom 후처리 효과
│   └── ShaderTypes.h            # 공유 uniform (브리징 헤더)
├── Data/
│   ├── ShipData.swift           # 8개 함선 정의 (속도, 데미지, 실드)
│   ├── LevelData.swift          # 99개 레벨 구성
│   └── AchievementData.swift    # Game Center 업적 정의
└── GameCenterManager.swift      # 리더보드/업적 제출

## SpriteKit Scene Hierarchy

GameScene (SKScene)
├── backgroundLayer (zPosition: -100)
│   └── StarfieldNode (parallax scrolling, 3 layers)
├── gameLayer (zPosition: 0)
│   ├── playerShip (zPosition: 10)
│   ├── enemyContainer (zPosition: 5)
│   ├── bulletPool (zPosition: 8) — pre-allocated 50 bullets
│   └── powerUpContainer (zPosition: 3)
├── effectsLayer (zPosition: 50)
│   └── ParticleManager (explosion + trail emitters)
└── hudLayer (zPosition: 100)
    ├── scoreLabel (SKLabelNode)
    ├── healthBar (custom SKShapeNode)
    └── levelLabel (SKLabelNode)

## Physics Categories

struct PhysicsCategory {
    static let none:      UInt32 = 0
    static let player:    UInt32 = 0b1        // 1
    static let enemy:     UInt32 = 0b10       // 2
    static let bullet:    UInt32 = 0b100      // 4
    static let powerUp:   UInt32 = 0b1000     // 8
    static let shield:    UInt32 = 0b10000    // 16
    static let bossBullet:UInt32 = 0b100000   // 32
}

// Contact pairs:
// player + enemy → damage
// player + powerUp → collect
// bullet + enemy → destroy
// player + bossBullet → damage

## Game State Machine

.menu → .playing → .paused → .playing
                 → .gameOver → .menu
                 → .bossIntro → .playing
                 → .levelComplete → .playing (next level)

## Metal Post-Processing

- Bloom shader: `BloomShader.metal` — multi-pass Gaussian blur + additive blend
- Uniforms: `PostProcessUniforms { float intensity; float threshold; float2 resolution; }`
- Applied after SpriteKit renders each frame via `SKView.presentScene(:transition:)`
- DO NOT modify Metal shaders without testing on device

## Build & Test

xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' build
xcodebuild -scheme StarfieldDestroyer -destination 'platform=iOS Simulator,name=iPhone 16 Pro' test

## Rules

- NEVER modify .pbxproj
- NEVER modify PhysicsCategory bitmasks (breaks all collision detection)
- NEVER change the scene hierarchy z-ordering without understanding render order
- NEVER modify ShaderTypes.h without updating both Swift and Metal references
- Add new enemies by subclassing EnemyShip, not by modifying it
- Bullet pooling: recycle via removeFromParent() + re-add, never allocate new
- Game Center: always check isAuthenticated before submitting scores

실제 CLAUDE.md: amp97 (Metal + 오디오 시각화 — 41 파일)

Metal 프로젝트는 가장 많은 프레임워크별 컨텍스트가 필요합니다. 에이전트가 시각적 출력을 검증할 수 없기 때문입니다:



# amp97 - Audio Visualizer

**Bundle ID:** `com.941apps.amp97`
**Target:** iOS 26+
**Architecture:** Metal render pipeline + AVAudioEngine analysis
**Swift version:** 6.2

## Architecture

Audio Input (microphone/file)
    → AVAudioEngine tap
    → FFT (vDSP)
    → Frequency/amplitude buffers
    → Metal compute shader (analysis)
    → Metal render pipeline (visualization)
    → CADisplayLink (60fps)
    → MTKView

## File Structure

amp97/
├── amp97App.swift                # 앱 진입점
├── Audio/
│   ├── AudioEngine.swift         # AVAudioEngine 설정, 탭 설치
│   ├── FFTProcessor.swift        # vDSP FFT, 주파수 빈 추출
│   ├── AudioBuffer.swift         # 오디오 데이터용 링 버퍼
│   └── MicrophoneManager.swift   # 마이크 권한, 세션 구성
├── Rendering/
│   ├── MetalView.swift           # SwiftUI용 MTKView 래퍼
│   ├── Renderer.swift            # 메인 렌더 루프, 파이프라인 상태
│   ├── ShaderLibrary.swift       # 컴파일된 셰이더 관리
│   ├── BufferManager.swift       # 트리플 버퍼링된 uniform 갱신
│   └── TextureManager.swift      # 오프스크린 렌더 타겟
├── Shaders/
│   ├── Shaders.metal             # 정점 + 프래그먼트 셰이더
│   ├── AudioCompute.metal        # 오디오 분석 컴퓨트 커널
│   ├── PostProcess.metal         # Bloom, 컬러 그레이딩
│   └── ShaderTypes.h             # 공유 uniform (브리징 헤더)
├── Visualizations/
│   ├── WaveformViz.swift         # 오실로스코프 스타일 파형
│   ├── SpectrumViz.swift         # 주파수 스펙트럼 막대
│   ├── CircularViz.swift         # 방사형 시각화
│   └── VizSelector.swift         # 시각화 전환
├── Views/
│   ├── MainView.swift            # 오버레이를 가진 풀스크린 시각화
│   ├── ControlsOverlay.swift     # 재생/정지, 시각화 선택, 게인
│   └── SettingsView.swift        # 오디오 소스, 감도
└── Extensions/
    ├── SIMD+Extensions.swift     # 벡터 수학 헬퍼
    └── Color+Metal.swift         # UIColor → float4 변환

## Metal Pipeline

### Uniforms (ShaderTypes.h)
typedef struct {
    float time;
    float2 resolution;
    float audioLevel;       // 0.0-1.0 RMS amplitude
    float frequencyBins[64]; // FFT output, normalized
    float4x4 transform;
} Uniforms;

### Render Pipeline
1. Compute pass: AudioCompute.metal processes FFT data → texture
2. Render pass: Shaders.metal reads texture + uniforms → visualization
3. Post-process pass: PostProcess.metal applies bloom → final output

### Buffer Management
- Triple buffering with DispatchSemaphore(value: 3)
- Uniforms updated per-frame on CPU, consumed by GPU 1-2 frames later
- Audio data ring buffer: 4096 samples, lock-free single producer/consumer

## Rules

- NEVER modify ShaderTypes.h without updating BOTH Swift and Metal sides
- NEVER exceed 64 frequency bins (fixed buffer size in shader)
- NEVER test Metal visual output in simulator — device only
- NEVER modify the audio engine tap format (48kHz, mono, float32)
- Triple buffer discipline: always signal semaphore in completion handler
- Audio session: .playAndRecord category with .defaultToSpeaker option

프로젝트 크기에 따라 CLAUDE.md 확장하기

적절한 상세 수준은 파일 수와 프레임워크 복잡도에 달려 있습니다:

프로젝트 크기 | CLAUDE.md 깊이 | 예시
---|---|---
작음 (< 20 파일) | 정체성 + 파일 목록 + 규칙 | Reps(14파일): 기본 SwiftData 패턴, 빌드 명령, 금지
중간 (20-40 파일) | + 프레임워크 컨텍스트 + 핵심 패턴 | TappyColor(30파일): SpriteKit 씬 계층, 물리 카테고리, 게임 루프
큼 (40+ 파일) | + 아키텍처 다이어그램 + 관계 맵 + 멀티 타겟 정보 | Return(63파일): 크로스플랫폼 아키텍처, 세션 동기화 다이어그램, 플랫폼별 차이
전문적 (Metal/GPU) | + 파이프라인 다이어그램 + 공유 타입 정의 + 버퍼 레이아웃 | amp97(41파일): 렌더 파이프라인 단계, uniform 구조체, 버퍼 관리

과잉 문서화의 비용은 거의 0입니다(에이전트가 필요 없는 것은 건너뜀). 부족 문서화의 비용은 큽니다(에이전트가 코드베이스와 충돌하는 패턴을 만들어냄).

CLAUDE.md 체크리스트

iOS 프로젝트용 CLAUDE.md를 만들거나 감사할 때 이 체크리스트를 사용하세요:

  • [ ] Bundle ID와 deployment target 명시
  • [ ] Swift 버전과 아키텍처 패턴 명명
  • [ ] 인라인 목적 주석이 달린 파일 구조
  • [ ] 올바른 scheme과 destination이 포함된 빌드 명령
  • [ ] 올바른 scheme과 destination이 포함된 테스트 명령
  • [ ] MCP 선호 명시("xcodebuild보다 build_sim 선호")
  • [ ] @Observable 규칙(ObservableObject 절대 사용 안 함)
  • [ ] NavigationStack 규칙(NavigationView 절대 사용 안 함)
  • [ ] .pbxproj 금지
  • [ ] 프레임워크별 컨텍스트(HealthKit 권한, SwiftData 관계, SpriteKit 계층, Metal 파이프라인)
  • [ ] 플랫폼 가용성 가드 문서화(#if canImport, #if os)
  • [ ] 핵심 싱글톤과 공유 패턴 문서화
  • [ ] 알려진 한계나 함정 명시

첫 에이전트 세션

MCP가 구성되고 프로젝트에 CLAUDE.md가 있는 상태에서, 효과적인 첫 세션을 안내합니다. Claude Code CLI를 사용하지만 워크플로는 어떤 런타임에도 적용됩니다.

1단계: 에이전트가 프로젝트를 인식하는지 확인



당신: 이 프로젝트를 요약해줘. 어떤 scheme으로 빌드해야 해?

Claude: [CLAUDE.md를 읽음]
        [MCP를 통해 discover_projs 호출]
        [MCP를 통해 list_schemes 호출]

        Return은 iOS 26+, watchOS, tvOS용 선(禪) 명상 타이머입니다.
        사용 가능한 scheme: Return, ReturnWatch, ReturnTV, ReturnTests.
        iOS 주 scheme: Return.

에이전트가 CLAUDE.md 내용을 참조하지 않으면, 그 파일이 프로젝트 루트(.xcodeprojPackage.swift와 같은 디렉터리)에 있는지 확인하세요.

2단계: 헬스 체크 빌드 실행



당신: iOS 시뮬레이터용으로 Return scheme을 빌드하고 결과를 보고해.

Claude: [list_sims 호출 — iOS 26.2의 iPhone 16 Pro 발견]
        [boot_sim 호출 — 시뮬레이터 부팅]
        [build_sim 호출 — 프로젝트 빌드]

        빌드 성공. 63개 소스 파일 컴파일됨.
        경고 2개:
        - HomeView.swift:132 — UIScreen.main이 iOS 26.0에서 deprecated 됨
        - LogWaterIntent.swift:61 — try?의 결과가 사용되지 않음
        오류 0.

3단계: 테스트 실행



당신: 모든 테스트를 실행하고 통과/실패를 보고해.

Claude: [test_sim 호출]

        테스트 12개 실행:
        ✓ TimerManagerTests (5/5 통과)
        ✓ SettingsTests (4/4 통과)
        ✓ ConstantsTests (3/3 통과)
        모든 테스트 통과.

4단계: 기능 구현



당신: 테마 시스템에 새로운 "Rain" 테마를 추가해줘. Theme.swift와 ThemeManager.swift의
     기존 패턴을 따라. 비 ambient 사운드도 포함해. 구현 후 빌드와 테스트를 진행해.

Claude: [Theme.swift 읽음 — Theme 구조체 패턴 이해]
        [ThemeManager.swift 읽음 — 테마 등록 이해]
        [기존 테마 정의 읽음]
        [기존 패턴을 따라 Theme.swift에 Rain 테마 추가]
        [ThemeManager.swift에 Rain 테마 등록]
        [build_sim 호출 — 빌드 성공]
        [test_sim 호출 — 모든 테스트 통과]

        Rain 테마를 추가했습니다:
        - Theme.swift: video, cover, ambient를 가진 새 `static let rain`
        - ThemeManager.swift: `allThemes` 배열에 추가됨
        - 빌드: 성공 (오류 0, 기존 경고 2)
        - 테스트: 12/12 통과

        참고: rain_ambient.wav를 프로젝트에 추가하고
        새 Theme.swift 변경을 Xcode 타겟에 수동으로 추가해야 합니다
        (저는 .pbxproj를 수정하지 않았습니다).

에이전트가 .pbxproj를 수정하지 않았다는 메모는 CLAUDE.md의 규칙 덕분입니다. 그 규칙이 없었다면 에이전트는 프로젝트 파일을 수정하려고 시도했을 것이고 아마 손상시켰을 것입니다.


에이전트가 iOS에서 잘하는 일

이는 에이전트가 일관되게 정확하고 프로덕션 준비가 된 출력을, 사람의 검토를 최소화하면서 만들어내는 작업들입니다.

SwiftUI 뷰와 modifier

에이전트는 SwiftUI 선언적 문법에 대한 깊은 패턴 인식을 가지고 있습니다. 뷰 합성, modifier 체인, 상태 바인딩, 레이아웃 — 이것들은 SwiftUI API 표면이 잘 문서화되어 있고 패턴이 매우 일관되기 때문에 에이전트의 학습 데이터에 잘 매핑됩니다.

에이전트가 뛰어난 곳:

  • 설명에서 새 뷰 만들기("X, Y, Z 토글을 가진 settings sheet를 만들어")
  • modifier 체인 적용 (.glassEffect(), .sensoryFeedback(), .navigationTitle())
  • 레이아웃 패턴 변환 (VStack에서 LazyVGrid로, List에서 ScrollView로)
  • SwiftData 모델에 @Bindable 폼 바인딩 구현
  • 샘플 데이터로 프리뷰 프로바이더 빌드

훌륭한 결과를 만드는 프롬프트 예시:



SettingsSheet.swift의 기존 패턴과 일치하는 SettingsView를 만들어줘. 다음 토글을 포함해:
- 햅틱 피드백 활성화 (Settings.shared.hapticsEnabled)
- HealthKit 로깅 활성화 (Settings.shared.healthKitEnabled)
- 세션 히스토리 표시 (SessionHistoryView로 이동하는 navigation link)

섹션 배경에 .glassEffect()를 적용한 Liquid Glass 스타일을 사용해.
ObservableObject가 아니라 @Observable 패턴을 따라.

구체성이 중요합니다. "settings view를 만들어"는 일반적인 출력을 만듭니다. "SettingsSheet.swift의 기존 패턴과 일치하는 SettingsView를 만들어"는 코드베이스와 일관된 출력을 만듭니다.

SwiftData 모델과 쿼리

에이전트는 SwiftData의 @Model 매크로, 관계, @Query 패턴을 안정적으로 처리합니다. 프레임워크의 선언적 본성(Django ORM이나 SQLAlchemy와 비슷)은 에이전트가 여러 코드베이스에서 본 패턴에 잘 매핑됩니다.

에이전트가 뛰어난 곳:

  • 관계가 있는 @Model 클래스 정의
  • sort descriptor와 predicate가 있는 @Query 작성
  • modelContext를 통한 CRUD 작업 구현
  • 스키마 버전 간 마이그레이션 계획
  • 프리뷰 데이터와 테스트 픽스처

에이전트가 안내가 필요한 곳:

  • 복잡한 #Predicate 표현식 (SwiftData의 predicate DSL에는 에이전트가 항상 알지 못하는 한계가 있음 — 알려진 한계를 CLAUDE.md에 문서화)
  • CloudKit 동기화 구성 (SwiftData를 통해 자동, 그러나 에이전트가 수동 동기화를 구현하려고 할 수 있음)

단위 테스트

에이전트가 작성한 단위 테스트는 iOS 프로젝트에서 일관되게 높은 품질을 보입니다. 에이전트는 XCTest 패턴, 비동기 테스트 메서드, setup/teardown 라이프사이클을 이해합니다.



TimerManager에 대한 단위 테스트를 다음 항목을 다루도록 작성해:
1. 초기 상태가 .stopped
2. start()가 .running으로 전이
3. pause()가 .paused로 전이
4. reset()이 원래 duration으로 .stopped로 돌아옴
5. 타이머가 올바르게 카운트다운 (3초 duration으로 테스트)

에이전트는 setUp()tearDown()이 잘 구조화된 XCTest 케이스, 적절한 단언, 타이머 기반 테스트를 위한 비동기 처리를 만들어냅니다.

리팩터링과 패턴 적용

에이전트는 기계적 리팩터링에 탁월합니다: 뷰를 컴포넌트로 추출, ObservableObject@Observable로 변환, NavigationView에서 NavigationStack으로 마이그레이션, 그리고 여러 파일에 걸쳐 일관된 패턴 적용.



Views/ 디렉터리의 모든 뷰를 ObservableObject 대신 @Observable을 사용하도록 리팩터링해줘.
@StateObject를 @State로, @ObservedObject를 직접 프로퍼티 접근으로,
@Published를 일반 프로퍼티로 업데이트해.

에이전트는 각 파일을 체계적으로 작업하며, 변환을 올바르게 적용하고, 기존 기능을 유지합니다. 이는 레버리지가 큰 작업입니다 — 수동 편집으로 한 시간이 걸릴 리팩터링이 거의 완벽한 정확도로 몇 분 안에 완료됩니다.

MCP를 통한 빌드 오류 진단

구조화된 MCP 출력으로, 에이전트는 대부분의 개발자보다 빠르게 빌드 오류를 진단합니다. 에이전트는 오류 JSON을 읽고, 정확한 파일과 줄을 식별하며, 오류 메시지를 이해하고, 수정을 적용합니다 — 종종 단일 턴에.

에이전트가 자율적으로 수정하는 오류:

  • 누락된 import
  • 타입 불일치
  • 프로토콜 conformance 누락
  • deprecated API 사용 (대체 제공)
  • 누락된 필수 initializer 매개변수
  • 접근 제어 위반

에이전트가 도움이 필요한 오류:

  • 모호한 타입 해결 (여러 모듈이 같은 타입을 정의)
  • 복잡한 generic 제약 실패
  • 매크로 확장 오류 (에이전트는 확장된 매크로 출력을 볼 수 없음)

시뮬레이터 관리

에이전트는 MCP를 통해 시뮬레이터 라이프사이클을 잘 처리합니다:



iOS 26에서 iPhone 16 Pro 시뮬레이터를 부팅하고, 앱을 설치한 다음 스크린샷을 찍어.

에이전트는 사용 가능한 런타임을 찾기 위해 list_sims를 호출하고, 시뮬레이터를 시작하기 위해 boot_sim을, 빌드하고 설치하기 위해 build_sim을, 캡처하기 위해 screenshot을 호출합니다 — 모두 구조화된 MCP 호출을 통해.


에이전트가 iOS에서 잘 못하는 일

에이전트가 실패하는 곳에 대한 솔직한 회계. 이 경계를 알면 좌절과 토큰 낭비를 막아줍니다.

.pbxproj 파일 수정 — 절대 금지

이는 iOS 에이전트 개발에서 가장 중요한 단일 규칙입니다. .pbxproj 파일은 Xcode의 프로젝트 구성 — UUID 참조, 빌드 단계 목록, 타겟 멤버십이 있는 구조화된 텍스트 파일입니다. 명목상으로는 사람이 읽을 수 있지만 실질적으로 AI 에이전트는 파싱할 수 없습니다.

에이전트가 .pbxproj에서 실패하는 이유:

  • 파일이 위치적 의미가 있는 커스텀 포맷(JSON도, YAML도, XML도 아닌)을 사용
  • 모든 항목이 UUID로 교차 참조됨 — 파일 추가는 3-5개 다른 섹션을 일관되게 갱신해야 함
  • 잘못 배치된 단일 문자가 전체 프로젝트 파일을 손상시킴
  • Xcode의 .pbxproj 머지 충돌 해결은 이미 취약함 — 에이전트 편집은 그것을 더 악화시킴

에이전트가 .pbxproj를 편집할 때 일어나는 일:

  1. 편집이 성공한 것처럼 보임 (에이전트가 "파일 갱신됨"이라고 보고)
  2. Xcode가 프로젝트 열기를 거부함 ("프로젝트 파일이 손상되었습니다")
  3. git 히스토리에서 복구하느라 15-60분을 소비
  4. PreToolUse hook을 추가하는 법을 배움 (Hooks 참조)

워크플로: 에이전트는 Swift 파일을 만듭니다. 당신이 그것들을 Xcode 프로젝트에 수동으로 추가합니다(Xcode로 드래그하거나 File > Add Files). 이는 파일당 5초가 걸리고 몇 시간의 복구를 막습니다.

Swift Package Manager 프로젝트의 경우: 이 한계는 덜 심각합니다. Package.swift는 에이전트가 안정적으로 편집할 수 있는 표준 Swift 파일입니다. 프로젝트가 SPM만 사용한다면(.xcodeproj 없이), 에이전트가 전체 프로젝트 구조를 관리할 수 있습니다.

복잡한 Interface Builder / Storyboard 편집

프로젝트가 Interface Builder(.xib 파일)나 Storyboard(.storyboard 파일)를 사용한다면, 에이전트는 그것들을 의미 있게 편집할 수 없습니다. 이것들은 자동 생성된 UUID, 제약 참조, outlet 연결을 가진 XML 파일이며, 텍스트 편집이 아닌 시각적 편집을 위해 설계되었습니다.

완화책: 새 뷰에는 SwiftUI만 사용하세요. 프로젝트에 레거시 Interface Builder 파일이 있다면 그대로 두고 새 UI는 SwiftUI로 만드세요.

성능 최적화

에이전트는 올바른 코드를 작성하지만 반드시 성능이 좋은 코드는 아닙니다. 앱을 프로파일링하거나, 병목을 식별하거나, 프레임률을 측정할 수 없습니다. 성능 최적화는 다음을 요구합니다:

  1. Instruments 프로파일링 (시각적 도구, 에이전트가 접근할 수 없음)
  2. 특정 디바이스의 GPU/CPU 특성 이해
  3. 측정 주도의 반복적 변경

이게 드러나는 곳:

  • Metal 셰이더 최적화 (에이전트는 유효한 Metal을 작성하지만 GPU 프레임 시간을 측정할 수 없음)
  • SwiftUI view body 복잡도 (에이전트가 redraw 오버헤드를 일으키는 깊게 중첩된 뷰를 만듦)
  • Core Data / SwiftData 페치 최적화 (에이전트가 큰 데이터셋에서 느릴 수 있는 올바른 쿼리를 작성)

완화책: 구현에는 에이전트를 사용하고, Instruments로 수동 프로파일링한 다음, 식별한 특정 최적화를 적용해 달라고 에이전트에 요청하세요.

코드 사이닝과 프로비저닝

에이전트는 오류 메시지를 읽는 것 이상으로 코드 사이닝 이슈를 디버그할 수 없습니다. 프로비저닝 프로파일 관리, 인증서 생성, entitlement 구성, App Store 제출은 Apple Developer 포털, Keychain Access, Xcode의 사이닝 UI를 포함하는 근본적으로 사람이 운영하는 워크플로입니다.

에이전트가 보는 것: "Signing for 'Return' requires a development team."

에이전트가 볼 수 없는 것: 인증서가 만료되었는지, 프로비저닝 프로파일이 디바이스를 포함하는지, 번들 ID가 App ID와 일치하는지, entitlements 파일이 올바른지.

완화책: 모든 사이닝은 Xcode의 Signing & Capabilities 탭에서 처리하세요. 에이전트에게 사이닝 실패를 디버그해 달라고 요청하지 마세요.

복잡한 Metal 셰이더 디버깅

에이전트는 문법적으로 올바른 Metal Shading Language(MSL)를 작성하지만 시각적 출력을 검증하거나 GPU 측 이슈를 디버그할 수 없습니다. Metal 셰이더는 GPU에서 실행됩니다 — 에이전트는 셰이더가 올바른 시각적 결과를 만드는지 피드백 메커니즘이 없습니다.

Metal로 에이전트가 할 수 있는 것:

  • 설명에서 vertex와 fragment 셰이더 작성
  • Swift에서 Metal 렌더 파이프라인 설정
  • 데이터 병렬 작업을 위한 compute 셰이더 생성
  • .metal 파일의 컴파일 오류 수정

Metal로 에이전트가 할 수 없는 것:

  • 셰이더 출력의 시각적 정확성 검증
  • GPU 성능 디버그 (프레임 시간, occupancy, 메모리 대역폭)
  • 시각적 아티팩트 진단 (밴딩, 정밀도 이슈, 잘못된 색공간)
  • 다른 GPU 아키텍처에서 테스트 (A 시리즈와 M 시리즈 동작 차이)

완화책: Metal 셰이더는 실제 디바이스에서 테스트하세요. Simulator의 Metal 구현은 디바이스 GPU 동작을 대표하지 않습니다. 시각적 디버깅에는 Xcode의 GPU Frame Capture를 사용하세요.

시각적 레이아웃 검증

에이전트는 앱의 UI를 볼 수 없습니다. SwiftUI 레이아웃 코드를 작성하고 컴파일을 검증할 수는 있지만, 결과 화면이 올바르게 보이는지는 알 수 없습니다. 10픽셀 어긋나거나, 잘못된 폰트 굵기를 사용하거나, 요소가 겹치는 뷰는 빌드 오류를 만들지 않으며 모든 로직 테스트를 통과합니다.

완화책: UI 변경을 시각적으로 검토하세요. Xcode의 SwiftUI 프리뷰(또는 헤드리스 렌더링을 위한 Apple MCP의 RenderPreview)를 사용해 레이아웃을 검증하세요. 자동화된 시각적 회귀 검출을 위해 swift-snapshot-testing 같은 라이브러리로 스냅샷 테스트를 고려하세요.


iOS 개발을 위한 Hooks

Hook은 에이전트의 워크플로의 특정 지점에서 결정론적으로 실행되는 셸 명령입니다. 강제 메커니즘 — "제발 .pbxproj를 편집하지 말아 주세요"(에이전트가 무시할 수 있는 제안)와 ".pbxproj를 편집할 수 없습니다"(하드 차단)의 차이입니다.

hook 시스템에 대한 배경은 Claude Code hooks 가이드를 참조하세요. 이 절은 iOS별 hook 패턴을 다룹니다.

PreToolUse: .pbxproj 쓰기 차단

iOS 프로젝트에서 가장 중요한 hook입니다. 에이전트가 .pbxproj 파일, .xcodeproj/ 디렉터리, 기타 Xcode 관리 파일에 쓰는 것을 차단합니다:



{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files. Create Swift files and add to Xcode manually.\" >&2; exit 2; fi'"
      }
    ]
  }
}

이걸 프로젝트 루트의 .claude/settings.json이나 전역 보호를 위한 ~/.claude/settings.json에 두세요.

작동 방식: 에이전트가 패턴과 일치하는 파일에 Edit 또는 Write 도구를 사용하려 하면, hook이 실행되어 파일 경로를 감지하고, 경고를 stderr로 출력하며, 코드 2(도구 사용을 차단)로 종료합니다. 에이전트는 오류 메시지를 받고 접근 방식을 조정합니다.

잡아내는 것: - 직접 .pbxproj 편집 - .xcodeproj/ 또는 .xcworkspace/ 디렉터리 내부의 모든 파일 - Interface Builder 파일 (.xib, .storyboard)

PostToolUse: SwiftFormat으로 저장 시 포맷



{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
      }
    ]
  }
}

요구사항: SwiftFormat이 설치되어 있어야 합니다(brew install swiftformat).

왜 중요한가: 에이전트는 문법적으로 올바른 Swift를 만들지만 포맷 컨벤션을 일관되게 따르지는 않습니다. SwiftFormat은 들여쓰기, 중괄호 위치, import 순서를 정규화합니다. 저장 시 포맷 hook은 에이전트가 건드린 모든 Swift 파일이 당신이 보기 전에 자동으로 포맷됨을 의미합니다.

선택적: 프로젝트 루트에 .swiftformat 구성 파일을 추가 해 포맷팅 규칙을 커스터마이즈할 수 있습니다:



# .swiftformat
--indent 4
--allman false
--stripunusedargs closure-only
--importgrouping testable-bottom
--header strip

PostToolUse: SwiftLint 자동 실행

SwiftLint를 사용한다면 모든 Swift 파일 편집 후 실행하세요:



{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftlint lint --path \"$FP\" --quiet 2>/dev/null || true; fi'"
      }
    ]
  }
}

|| true는 lint 경고가 에이전트를 차단하지 않도록 막습니다. lint 위반이 차단되도록 하려면 제거하세요.

PostToolUse: 변경 후 자동 빌드

공격적인 피드백 루프를 위해 모든 Swift 파일 변경 후 빌드를 트리거하세요:



{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then xcodebuild -scheme Return -destination \"platform=iOS Simulator,name=iPhone 16 Pro\" build 2>&1 | tail -5; fi'"
      }
    ]
  }
}

경고: 이건 비용이 큽니다. 모든 파일 편집이 빌드를 트리거합니다. 아껴 쓰세요 — 즉시 빌드 피드백이 필요한 디버깅 세션에 가장 유용합니다. 일반 개발에서는 에이전트가 준비됐을 때 MCP를 통해 직접 빌드를 트리거하게 두세요.

PreToolUse: Entitlement 수정 차단

entitlements 파일을 우발적인 에이전트 수정으로부터 보호하세요:



{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.entitlements$\"; then echo \"BLOCKED: Do not modify entitlements files without explicit permission.\" >&2; exit 2; fi'"
      }
    ]
  }
}

통합된 iOS hook 구성

제가 모든 iOS 프로젝트에서 사용하는 전체 .claude/settings.json입니다:



{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard|entitlements)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode-managed files. Create Swift files and add manually.\" >&2; exit 2; fi'"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.swift$\"; then swiftformat \"$FP\" --quiet 2>/dev/null; fi'"
      }
    ]
  }
}

이는 두 가지 보장을 줍니다: 1. 에이전트가 Xcode 프로젝트 파일을 손상시킬 수 없음(PreToolUse 차단) 2. 에이전트가 건드린 모든 Swift 파일이 자동 포맷됨(PostToolUse 포맷)


에이전트와 잘 작동하는 아키텍처 패턴

모든 Swift 아키텍처가 똑같이 에이전트 친화적이지는 않습니다. 다음 패턴들은 명시적이고, 일관되며, 학습 데이터에 잘 표현되어 있기 때문에 가장 좋은 결과를 만듭니다.

@Observable (ObservableObject 절대 안 됨)

iOS 26+ 타겟은 @Observable만 사용해야 합니다. 이는 모던 패턴이자 에이전트 친화적인 패턴입니다:



// CORRECT — @Observable
@Observable
@MainActor
final class TimerManager {
    var timeRemaining: TimeInterval = 0
    var state: TimerState = .stopped

    func start() {
        state = .running
        // ...
    }
}

// In a view:
struct TimerView: View {
    @State private var timer = TimerManager()

    var body: some View {
        Text(timer.timeRemaining, format: .number)
    }
}



// WRONG — ObservableObject (deprecated pattern)
class TimerManager: ObservableObject {
    @Published var timeRemaining: TimeInterval = 0
    @Published var state: TimerState = .stopped
}

// WRONG — @StateObject (deprecated pattern)
struct TimerView: View {
    @StateObject private var timer = TimerManager()
}

@Observable이 에이전트 친화적인 이유: 패턴이 더 단순하고(@Published 어노테이션이 필요 없음), 소유 모델이 더 명확하며(@StateObject@ObservedObject 대신 @State), 움직이는 부품이 적기 때문에 에이전트가 버그를 덜 만듭니다.

CLAUDE.md에 문서화하세요: iOS 26이 타겟이더라도 에이전트는 학습 데이터의 ObservableObject 패턴으로 가끔 회귀합니다. 명시적 금지가 이를 방지합니다.

NavigationStack (NavigationView 절대 안 됨)



// CORRECT
NavigationStack {
    List(items) { item in
        NavigationLink(value: item) {
            ItemRow(item: item)
        }
    }
    .navigationDestination(for: Item.self) { item in
        ItemDetailView(item: item)
    }
}

// WRONG
NavigationView {
    List(items) { item in
        NavigationLink(destination: ItemDetailView(item: item)) {
            ItemRow(item: item)
        }
    }
}

NavigationStack은 iOS 16+이며 새 코드에서 사용해야 할 유일한 내비게이션 패턴입니다. 타입 안전 navigationDestination(for:) 패턴은 에이전트가 잘못된 navigation link를 만드는 것을 방지합니다.

영속성을 위한 SwiftData

SwiftData 모델은 에이전트 보조 개발에 가장 깔끔한 영속성 패턴입니다:



@Model
final class GroceryItem {
    var name: String
    var quantity: Int
    var isCompleted: Bool
    var category: Category?
    var list: GroceryList?

    init(name: String, quantity: Int = 1) {
        self.name = name
        self.quantity = quantity
        self.isCompleted = false
    }
}

SwiftData를 다루는 에이전트를 위한 핵심 규칙: 1. @Model 클래스는 자동으로 Observable 입니다 — @Observable을 추가하지 마세요 2. 폼 바인딩에는 @Bindable 을 사용하세요: @Bindable var item: GroceryItem 3. 뷰의 반응형 데이터에는 @Query 를 사용하세요: @Query var items: [GroceryItem] 4. 비뷰 코드에서는 modelContext.fetch() 를 사용하세요 5. 관계 삭제는 명시적 규칙이 필요합니다: .cascade, .nullify, .deny

Swift 6.2 동시성

새 프로젝트는 Swift 6.2 strict concurrency를 타겟으로 하세요:



// Actor isolation for shared mutable state
@MainActor
@Observable
final class DataManager {
    var items: [Item] = []

    func loadItems() async throws {
        let fetched = try await api.fetchItems()
        items = fetched  // Safe: @MainActor isolated
    }
}

// Sendable conformance for cross-actor transfers
struct Item: Sendable, Identifiable {
    let id: UUID
    let name: String
    let createdAt: Date
}

동시성을 위한 에이전트 안내: - 모든 view model을 @MainActor로 표시(데이터 경합 경고 방지) - 모든 비동기 작업에 async/await 사용(completion handler 사용 안 함) - 액터 간 전송을 위해 값 타입을 Sendable로 만듦 - 비동기 초기화에는 뷰에서 Task { } 사용 - 성능 필요를 측정한 경우에만 nonisolated 사용

Liquid Glass 디자인 시스템 (iOS 26+)

iOS 26은 Liquid Glass 디자인 시스템을 도입했습니다. 명시적인 안내가 주어지면 에이전트가 잘 처리합니다:



// Glass effect on containers
VStack {
    // content
}
.glassEffect()

// Glass effect with tint
Button("Action") { }
    .glassEffect(.regular.tint(.blue))

// Glass effect on navigation bars (automatic in iOS 26)
NavigationStack {
    // content
}
// Navigation bar automatically uses glass material

// Custom glass shapes
RoundedRectangle(cornerRadius: 16)
    .fill(.ultraThinMaterial)
    .glassEffect()

CLAUDE.md에 포함: "섹션 배경과 카드 컨테이너에 .glassEffect()를 사용하세요. 내비게이션 바는 iOS 26에서 자동으로 글래스 머티리얼을 채택합니다. 커스텀 머티리얼로 글래스 효과를 직접 재생성하지 마세요 — 시스템 modifier를 사용하세요."


프레임워크별 컨텍스트

각 Apple 프레임워크는 에이전트별 고려사항을 가집니다. 이 절은 8개 앱에서 사용된 프레임워크를 다룹니다.

HealthKit

사용한 앱: Return, Water

HealthKit은 신중한 권한 처리와 플랫폼 가드를 요구합니다:



// Always check availability and authorization
import HealthKit

@MainActor
@Observable
final class HealthKitManager {
    private let store = HKHealthStore()
    var isAuthorized = false

    func requestAuthorization() async {
        guard HKHealthStore.isHealthDataAvailable() else { return }

        let types: Set<HKSampleType> = [
            HKQuantityType(.dietaryWater),
            HKCategoryType(.mindfulSession)
        ]

        do {
            try await store.requestAuthorization(toShare: types, read: types)
            isAuthorized = true
        } catch {
            // User denied — do not retry automatically
        }
    }
}

HealthKit을 위한 에이전트 규칙: - 항상 HKHealthStore.isHealthDataAvailable()로 가드 - 권한을 추정하지 말 것 — 모든 쓰기에서 확인 - 멀티플랫폼 코드에는 #if canImport(HealthKit) 사용(HealthKit은 tvOS에서 사용 불가) - HealthKit이 제공하는 것 이상으로 건강 데이터를 로컬에 저장하지 말 것 - Info.plist에 NSHealthShareUsageDescriptionNSHealthUpdateUsageDescription 모두 포함

SpriteKit

사용한 앱: TappyColor, Starfield Destroyer

SpriteKit의 씬 그래프 모델은 명시적 에이전트 안내를 요구합니다:



## SpriteKit Rules

- Scene hierarchy is a tree of SKNodes with zPosition ordering
- Physics bodies use category bitmasks (UInt32) for collision detection
- Node pooling: pre-allocate reusable nodes (bullets, particles)
- Never add nodes directly to the scene — use layer nodes for organization
- Update loop: `update(_ currentTime:)` runs every frame — keep it fast
- Actions: use SKAction sequences for animations, not manual property updates
- Textures: use texture atlases for performance (.atlas directories)

SpriteKit에서 에이전트 강점: - SKAction 시퀀스와 그룹 만들기 - 물리 바디와 컨택트 검출 설정 - 게임 상태 머신 구현 - HUD 오버레이 빌드

SpriteKit에서 에이전트 약점: - 성능에 민감한 게임 루프 (에이전트가 프레임당 불필요한 작업을 추가) - 복잡한 물리 시뮬레이션 (정밀도에서는 커스텀 물리가 SKPhysicsBody를 능가) - 파티클 효과 튜닝 (시각적, 반복 필요)

Metal

사용한 앱: amp97, Water, Starfield Destroyer

Metal은 에이전트가 가장 어려워하는 프레임워크입니다. GPU 프로그래밍 모델이 CPU 측 Swift와 근본적으로 다르고, 에이전트가 시각적 출력을 검증할 수 없기 때문입니다.



## Metal Rules

- Shared types between Swift and Metal go in a bridging header (ShaderTypes.h)
- Triple buffer in-flight frames (semaphore with value 3)
- Test shaders on DEVICE, not simulator (Metal behavior differs)
- Compute shaders: threadgroup size must divide evenly into grid size
- Fragment shaders: output color must be in correct color space (sRGB or linear)
- DO NOT optimize shaders without Instruments GPU profiling data

Metal 프로젝트의 CLAUDE.md에 포함할 것: - Uniforms 구조체 정의(Swift와 MSL 사이 공유) - 렌더 파이프라인 상태 설정 패턴 - 버퍼 인덱스와 그 목적 - 어떤 셰이더가 존재하고 각각 무엇을 하는지 - 알려진 정밀도 이슈(half 대 float)

Live Activities

사용한 앱: Return

Live Activities는 일단 문서화되면 에이전트가 잘 처리하는 특정 구성을 요구합니다:



## Live Activities

- ActivityAttributes defined in `TimerActivityAttributes.swift`
- ActivityKit framework: `import ActivityKit`
- Widget extension: `ReturnWidgets/ReturnLiveActivity.swift`
- Start: `Activity<TimerActivityAttributes>.request(attributes:content:)`
- Update: `activity.update(ActivityContent(state:staleDate:))`
- End: `activity.end(ActivityContent(state:staleDate:), dismissalPolicy:)`
- Push token: register for updates via `activity.pushTokenUpdates`

Game Center

사용한 앱: Starfield Destroyer



## Game Center

- Authentication: `GKLocalPlayer.local.authenticateHandler`
- Leaderboards: `GKLeaderboard.submitScore(_:context:player:leaderboardIDs:completionHandler:)`
- Achievements: `GKAchievement.report(_:withCompletionHandler:)` (takes `[GKAchievement]` array)
- Always check `GKLocalPlayer.local.isAuthenticated` before submitting
- Handle authentication failure gracefully (offline play must work)


멀티플랫폼 패턴

Return은 iOS, watchOS, tvOS에 걸쳐 있습니다. 에이전트와의 멀티플랫폼 개발은 명시적인 플랫폼 경계 문서화를 요구합니다.

공유 코드 조직



Shared/
├── MeditationSession.swift    # 데이터 모델 (모든 플랫폼)
├── SessionStore.swift         # iCloud 동기화 (모든 플랫폼)
└── SessionHistoryView.swift   # UI (플랫폼별 적응)

Return/                        # iOS 전용
ReturnWatch Watch App/         # watchOS 전용
ReturnTV/                      # tvOS 전용

에이전트 규칙: "파일이 Shared/에 있다면 변경은 모든 플랫폼에 영향을 줍니다. 파일이 플랫폼 디렉터리에 있다면 변경은 격리됩니다. 파일을 수정하기 전에 항상 어느 디렉터리에 있는지 확인하세요."

플랫폼 가용성 가드



// HealthKit: available on iOS and watchOS, not tvOS
#if canImport(HealthKit)
import HealthKit
// HealthKit code here
#endif

// ActivityKit: available on iOS only
#if canImport(ActivityKit)
import ActivityKit
// Live Activity code here
#endif

// WatchKit: available on watchOS only
#if os(watchOS)
import WatchKit
// Watch-specific code here
#endif

에이전트 안내: "플랫폼별 프레임워크를 사용할 때는 항상 #if canImport() 또는 #if os() 가드를 사용하세요. 프레임워크가 모든 타겟에서 사용 가능하다고 가정하지 마세요."

플랫폼별 UI 적응



struct SessionHistoryView: View {
    @Query var sessions: [MeditationSession]

    var body: some View {
        List(sessions) { session in
            SessionRow(session: session)
        }
        #if os(tvOS)
        .focusable()
        #endif
        #if os(iOS)
        .swipeActions {
            Button("Delete", role: .destructive) {
                // delete
            }
        }
        #endif
    }
}


고급 워크플로

자율 빌드-테스트-수정 루프

가장 강력한 패턴: 에이전트에게 기능 명세를 주고 빌드-테스트-수정 사이클을 자율적으로 반복하게 하는 것입니다.



다음의 카운트다운 타이머를 구현해:
1. 사용자가 선택한 duration(10, 20, 30분)에서 시작
2. 원형 진행 표시기로 남은 시간 표시
3. 완료 시 종소리 재생
4. mindful minutes로 세션을 HealthKit에 로깅

매 변경 후 빌드해. 모든 오류를 수정해. 빌드가 성공하면 테스트를 실행해.
모든 테스트가 통과하고 빌드가 깨끗할 때까지 계속해.

에이전트가 코드를 작성하고, MCP를 통해 빌드하고, 구조화된 오류를 읽고, 수정하고, 반복합니다. 사람의 빌드-오류-수정 사이클이 5-10번 필요할 기능이 단일 자율 루프에서 완료됩니다.

작동하는 경우: 명확한 수용 기준이 있는 잘 정의된 기능.

깨지는 경우: 개방형 기능("멋지게 보이게 해줘"), 성능에 민감한 코드, 또는 시각적 검증이 필요한 모든 것.

iOS를 위한 서브에이전트 위임

Claude Code의 서브에이전트 시스템은 iOS 프로젝트에서 작동합니다:



iOS, watchOS, tvOS에서 명상 세션을 위한 iCloud key-value 스토어 동기화를 구현하는
가장 좋은 접근법을 서브에이전트로 조사해줘. 권장 패턴을 보고해.

서브에이전트는 별도 컨텍스트 윈도우에서 문서와 코드 패턴을 탐색하고, 요약을 반환하며, 메인 세션이 권장 사항을 구현합니다. 이는 조사가 주 컨텍스트를 소비하는 것을 막아 줍니다.

앱 간 패턴 적용

일관된 패턴을 가진 여러 iOS 앱을 유지할 때, 에이전트는 한 앱의 패턴을 다른 앱에 적용할 수 있습니다:



Return 프로젝트의 Settings.swift가 어떻게 작동하는지 보세요
(검증이 있는 중앙 집중형 싱글톤). 같은 패턴을 적용해
Water 프로젝트의 Settings.swift를 만들어줘.

에이전트는 소스 패턴을 읽고, 구조를 이해하며, 타겟 프로젝트에 일관된 구현을 만듭니다.

듀얼 에이전트 검토 (Claude + Codex)

중요한 변경에는 다른 모델 군에서 두 개의 에이전트를 사용하세요:

  1. Claude Code가 구현을 작성
  2. Codex CLI가 별도 패스에서 검토


# Claude가 기능을 구현한 후:
codex "마지막 커밋의 변경을 검토해. Swift 6.2 동시성 정확성,
      SwiftData 관계 무결성, 잠재적 retain cycle에 초점을 맞춰.
      이슈만 보고해 — 칭찬은 하지 마."

다른 모델 군은 다른 종류의 오류를 잡습니다. 미묘한 버그를 도입하기 쉬운 Metal 셰이더와 동시성 패턴에서 특히 가치 있습니다.

듀얼 검토가 단일 검토에서 놓치는 것을 잡는 것:

이슈 타입 | Claude 강점 | Codex 강점
---|---|---
SwiftData 관계 사이클 | 보통 | 강함 (GPT-4o)
@MainActor isolation 누락 | 강함 | 보통
Metal 버퍼 정렬 | 보통 | 보통
Retain cycle 검출 | 강함 (Opus) | 강함 (o3)
API deprecation 인지 | 강함 (더 최신 학습 데이터) | 보통
동시성 경합 조건 | 강함 | 강함 (다른 패턴 잡힘)

듀얼 검토는 더 많은 버그를 찾는 게 아닙니다 — 다른 버그를 찾는 것입니다. 각 모델 군은 패턴 인식에서 다른 실패 모드를 가집니다.

여러 앱에 걸친 배치 작업

프레임워크나 패턴 변경이 여러 앱에 영향을 줄 때:



# 모든 프로젝트에 @Observable 패턴 갱신
for project in BananaList Return Water Reps; do
  cd ~/Projects/$project
  claude -p "남아 있는 ObservableObject 사용을 모두 감사해.
             CLAUDE.md의 패턴을 따라 @Observable로 변환해.
             변경 후 빌드와 테스트를 실행해." --dangerously-skip-permissions
done

주의해서 사용하세요. --dangerously-skip-permissions 플래그는 비대화형 모드에 필요하지만 모든 안전 검사를 우회합니다. .pbxproj 파일을 보호하기 위해 PreToolUse hook이 설치되어 있는지 확인하세요.


실세계 케이스 스터디

추상적 조언은 쉽습니다. 다음은 8개 앱의 구체적 시나리오로, 에이전트 보조 iOS 개발이 실무에서 어떻게 작동하는지 — 실패도 포함해 — 보여줍니다.

케이스 스터디 1: Return에 TV 앱 추가 (성공)

작업: 이미 iOS와 watchOS 버전이 있는 명상 타이머 Return에 tvOS 타겟을 추가. TV 앱은 Siri Remote 내비게이션, 큰 화면 UI, iOS 앱과의 설정 동기화가 필요했습니다.

에이전트가 잘한 것: - 기존 iOS TimerManager를 읽고 Live Activities와 HealthKit(tvOS에서 사용 불가)을 생략한 TVTimerManager 생성 - Siri Remote 포커스 내비게이션을 위한 커스텀 버튼 스타일 생성 (TVCapsuleButtonStyle, TVCircleButtonStyle) - 휠 피커(Siri Remote에서 사용 불가능)를 +/- 버튼으로 대체하는 TVStepper 컴포넌트 빌드 - App Groups(group.com.941apps.Return)를 통한 설정 동기화 구현 - 공유 코드 전반에 #if os(tvOS) 가드 추가 - MCP를 통해 platform=tvOS Simulator,name=Apple TV로 빌드와 테스트

제가 수동으로 해야 한 것: - Xcode에서 tvOS 타겟 생성(File > New > Target > tvOS App) - Xcode 프로젝트에 새 타겟 추가(.pbxproj 변경) - TV 타겟에 App Groups entitlement 구성 - 기존 scheme에 TV 타겟 추가 또는 새 scheme 생성 - 모든 에이전트 생성 Swift 파일을 TV 타겟에 수동 추가 - 손수 Siri Remote 내비게이션 테스트(에이전트는 포커스 동작을 평가할 수 없음)

결과: 15개의 새 Swift 파일, 완전히 작동하는 TV 앱이 약 3시간의 에이전트 보조 작업으로 구현되었습니다. 동등한 수동 구현은 1-2일이 걸렸을 것입니다. 에이전트가 코드의 약 80%를 처리했고, 저는 Xcode UI 상호작용과 수동 테스트가 필요한 20%를 처리했습니다.

케이스 스터디 2: amp97의 Metal 셰이더 디버깅 (부분 실패)

작업: 오실로스코프 셰이더에 에너지 기반 강도 시스템 추가. 시각화가 오디오 에너지에 따라 펄스해야 했습니다.

일어난 일: 1. 에이전트가 uEnergy uniform과 HDR 톤매핑을 추가하는 유효한 Metal 셰이더 수정을 작성 2. 코드가 오류 없이 컴파일됨 3. 디바이스에서 시각화가 완전히 흰색 — 강도 계수가 10배 너무 높음(0.30 대신 3.5) 4. 에이전트가 흰 화면을 볼 수 없으므로 피드백 신호 없음 5. 제가 시각적으로 이슈를 식별하고 에이전트에게 계수를 줄여 달라고 요청 6. 에이전트가 줄였지만 전체 에너지 상태 머신이 너무 복잡해 다른 방식으로 시각화기를 망가뜨림 7. 전체를 되돌림 — 두 커밋(67959ed, cda4830)을 869d914에서 되돌림

교훈: Metal 셰이더는 피드백 루프가 깨졌기 때문에 에이전트 보조 개발에서 가장 어려운 도메인입니다. 에이전트는 문법(컴파일됨)과 의미론(올바른 타입)은 검증할 수 있지만 출력(올바르게 보임)은 검증할 수 없습니다. 시각적 동작을 변경하는 셰이더 수정은 디바이스에서의 사람 검증을 요구합니다.

그 후 CLAUDE.md에 추가한 것: "오실로스코프 셰이더의 에너지 상태 수정은 매우 신중한 계수 테스트 없이 시도하지 마세요. 이전 시도가 10배 너무 높은 계수로 시각화기를 망가뜨렸습니다."

케이스 스터디 3: Banana List의 SwiftData 마이그레이션 (성공)

작업: 데이터 모델을 V1에서 V2로 마이그레이션. GroceryItemquantity 필드와 관계가 있는 새 Category 모델 추가.

에이전트가 한 일: 1. 기존 V1 모델 정의 읽음 2. 새 필드와 관계가 있는 V2 모델 정의 생성 3. SchemaMigrationPlan 프로토콜 conformance가 있는 GroceryMigrationPlan 작성 4. V1toV2 마이그레이션 스테이지 구현: 기본값 quantity: 1category: nil 추가 5. 새 필드를 지원하도록 모든 뷰 갱신 6. 프리뷰를 위한 SampleData.swift 갱신 7. MCP를 통해 빌드하고 테스트 실행 — 모두 통과 8. 마이그레이션별 단위 테스트 생성

핵심: SwiftData 마이그레이션은 Apple 문서와 학습 데이터에 철저히 표현된 잘 정의된 프로토콜 패턴을 따르기 때문에 에이전트가 성공했습니다. CLAUDE.md가 V1 모델을 명시적으로 문서화했기에 에이전트는 무엇으로부터 마이그레이션하는지 이해했습니다.

케이스 스터디 4: Return의 iCloud 세션 동기화 (복잡도가 있는 성공)

작업: 디바이스 간 명상 세션 로깅 구현. Apple TV나 Mac에서 완료된 세션이 HealthKit 로깅을 위해 iPhone으로 동기화되어야 함.

에이전트가 만든 것:



┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│    tvOS     │     │    Mac      │     │   Watch     │
│ TVTimerMgr  │     │ TimerMgr    │     │ WatchTimer  │
└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
       │                   │                   │
       └───────────────────┼───────────────────┘
                           │
                           ▼
              ┌────────────────────────┐
              │     SessionStore       │
              │  (iCloud Key-Value)    │
              └───────────┬────────────┘
                          │
                          ▼
              ┌────────────────────────┐
              │  iPhone (on foreground)│
              │  → Write to HealthKit  │
              └────────────────────────┘

에이전트는: 1. UUID, 날짜, duration, 소스 디바이스, HealthKit 동기화 상태가 있는 MeditationSession 데이터 모델 생성 2. iCloud 동기화를 위해 NSUbiquitousKeyValueStore를 관리하는 SessionStore 싱글톤 빌드 3. 머지 충돌 해결 구현(UUID 기반 중복 제거) 4. 플랫폼별 적응이 있는 SessionHistoryView 추가(iOS의 swipe-to-delete, tvOS의 포커스 기반) 5. 다른 디바이스의 세션을 위한 iPhone 측 HealthKit 동기화 연결

반복이 필요한 것: 초기 구현은 iPhone 앱이 백그라운드에서 시작되는 경우(동기화를 위한 포그라운드 알림 없음)를 처리하지 못했습니다. 에이전트는 구체적 안내가 필요했습니다: "백그라운드 KV 변경 시 동기화를 트리거하기 위해 NSUbiquitousKeyValueStore.didChangeExternallyNotification을 사용하세요." 그 힌트 후 구현은 정확했습니다.

교훈: 아키텍처가 명확히 설명되면 에이전트는 멀티플랫폼 아키텍처 패턴을 잘 처리합니다. iCloud 동기화 패턴은 사소하지 않지만, 에이전트가 이해한 문서화된 Apple 패턴을 따릅니다. 엣지 케이스(백그라운드 동기화)는 잘 문서화되어 있지 않기 때문에 사람의 도메인 지식이 필요했습니다.

케이스 스터디 5: Starfield Destroyer의 Game Center 통합 (성공)

작업: 우주 슈터에 Game Center 리더보드와 업적 추가.

에이전트가 잘한 것: - 앱 진입점에서 GKLocalPlayer.local.authenticateHandler 구현 - 스코어 제출과 업적 보고를 위한 메서드가 있는 GameCenterManager 생성 - 모든 Game Center 작업 전에 인증 상태 확인 추가 - 오프라인 케이스를 우아하게 처리(Game Center 없이도 게임 플레이, 재연결 시 제출) - 8 함선 진행 시스템과 일치하는 업적 정의 생성

수동 작업이 필요한 것: - App Store Connect에서 리더보드와 업적 생성(웹 포털, 에이전트가 접근할 수 없음) - Xcode에서 Game Center entitlement 구성 - 샌드박스 Game Center 계정으로 테스트(디바이스에서 수동 로그인 필요)


에이전트와의 프로젝트 라이프사이클

새 iOS 프로젝트 시작하기

에이전트 보조로 새 프로젝트를 시작하는 최적 워크플로:

1단계: 사람 설정 (15-30분) 1. Xcode 프로젝트 생성(File > New > Project) 2. 사이닝과 capability 구성 3. deployment target과 지원 destination 설정 4. 필요한 entitlement 추가(HealthKit, Game Center 등) 5. 프로젝트 정체성과 규칙이 담긴 초기 CLAUDE.md 생성

2단계: 에이전트 구현 (몇 시간 ~ 며칠) 1. 에이전트가 데이터 모델 생성(SwiftData, Core Data, 또는 일반 struct) 2. 에이전트가 문서화된 패턴을 따라 뷰 빌드 3. 에이전트가 manager/service 클래스로 비즈니스 로직 구현 4. 에이전트가 단위 테스트 작성 5. MCP를 통한 빌드-테스트-수정 루프(자율적)

3단계: 사람 통합 (30-60분) 1. 에이전트 생성 파일을 Xcode 타겟에 추가 2. 사이닝과 entitlement 검증 3. 실제 디바이스에서 테스트 4. 시각적 레이아웃과 UX 검토 5. App Store Connect에 제출

기존 프로젝트 유지보수

기존 앱의 지속적 개발을 위해:



당신: Return의 다음 기능: 세션 duration과 일관성에서 계산되는
     "Focus Score"를 추가해줘. 메인 타이머 뷰에 표시. 빌드와 테스트.

Claude: [CLAUDE.md를 읽고 패턴 이해]
        [TimerManager.swift, Settings.swift 읽음]
        [FocusScore.swift 생성 — 계산 로직이 있는 모델]
        [FocusScoreView.swift 생성 — 표시 컴포넌트]
        [ContentView.swift에 통합]
        [build_sim 호출 — 1 오류: import 누락]
        [import 수정]
        [build_sim 호출 — 성공]
        [FocusScoreTests.swift 작성]
        [test_sim 호출 — 모두 통과]

에이전트의 효율성은 CLAUDE.md가 프로젝트의 현재 상태를 얼마나 잘 반영하는지에 따라 확장됩니다. 중요한 새 기능을 추가하거나, 아키텍처 패턴을 변경하거나, 새 프레임워크를 도입할 때 CLAUDE.md를 갱신하세요.

에이전트를 참여시킬 때와 안 할 때

작업 | 에이전트? | 이유
---|---|---
새 SwiftUI 뷰 | 예 | 에이전트가 선언적 UI에 탁월
SwiftData 모델 변경 | 예 | 잘 정의되고 테스트 가능
단위 테스트 | 예 | 기계적, 패턴 기반
리팩터링 | 예 | 체계적, 다중 파일
빌드 오류 진단 | 예(MCP 경유) | 구조화된 피드백 루프
새 Xcode 타겟 | 아니오 | Xcode UI, .pbxproj 변경 필요
사이닝과 프로비저닝 | 아니오 | 포털 기반, 에이전트 접근 불가
시각적 마무리 | 아니오 | 사람의 미적 판단 필요
Metal 셰이더 튜닝 | 아니오 | 디바이스 GPU 테스트 필요
App Store 제출 | 아니오 | 포털과 Xcode Organizer
성능 프로파일링 | 아니오 | Instruments 필요
접근성 감사 | 부분적 | 에이전트가 라벨 추가, 사람이 VoiceOver 검증


에이전트 정의 구성하기

Claude Code의 에이전트 정의 시스템(.claude/agents/)을 사용한다면 iOS 전용 에이전트를 만드세요:



---
name: ios-developer
description: iOS development agent with MCP build tools and SwiftUI expertise
tools:
  - XcodeBuildMCP
  - xcode
---

# iOS Developer Agent

You are an iOS development agent for apps targeting iOS 26+ with SwiftUI.

## Architecture Rules
- @Observable for all view models (NEVER ObservableObject)
- NavigationStack for all navigation (NEVER NavigationView)
- SwiftData for persistence
- Swift 6.2 strict concurrency
- @MainActor on all Observable classes

## Build & Test — Always Use MCP

Prefer MCP tools over raw shell commands for ALL build operations:

- **Build**: `build_sim` / `build_device` (NOT `xcodebuild` via Bash)
- **Test**: `test_sim` / `test_device` (NOT `xcodebuild test` via Bash)
- **Simulators**: `list_sims`, `boot_sim`, `open_sim`
- **Debug**: `debug_attach_sim`, `debug_stack`, `debug_variables`
- **Apple docs**: `DocumentationSearch` (NOT WebSearch for Apple APIs)
- **Swift verification**: `ExecuteSnippet` (NOT `swift` via Bash)

MCP returns structured JSON. Bash returns unstructured text.

## File Management Rules
- NEVER modify .pbxproj, .xcodeproj/, .xcworkspace/, .xib, .storyboard
- Create Swift files in the correct directory
- Report files that need manual addition to Xcode targets

## SwiftData Rules
- @Model classes are automatically Observable — do not add @Observable
- Use @Bindable for form bindings to model properties
- Use @Query in views, modelContext.fetch() elsewhere
- Document relationship delete rules

## When You Get Stuck
- Build errors: use `build_sim` via MCP for structured output
- API questions: use `DocumentationSearch` via Apple MCP
- Swift verification: use `ExecuteSnippet` via Apple MCP
- Never guess — verify with tools

Claude Code 세션에서 @ios-developer로 이 에이전트를 참조하세요.


에이전트 보조 iOS의 테스트 패턴

명확한 안내가 주어지면 에이전트는 훌륭한 단위 테스트를 작성합니다. 가장 좋은 결과를 만드는 패턴들입니다.

테스트 파일 구조



# CLAUDE.md 안에:
## Test Structure

Tests mirror source structure:
- `ReturnTests/TimerManagerTests.swift` tests `TimerManager.swift`
- `ReturnTests/SettingsTests.swift` tests `Settings.swift`
- `ReturnTests/ConstantsTests.swift` tests `Constants.swift`

Test naming: `test_<what>_<condition>_<expected>`
Example: `test_start_whenStopped_transitionsToRunning`

테스트 프롬프트

효과적인 테스트 프롬프트:



TimerManager에 대한 단위 테스트를 다음을 포함하도록 작성해:

1. 초기 상태가 .stopped이고 timeRemaining == selectedDuration
2. start()가 상태를 .running으로 전이
3. .running에서 pause()가 .paused로 전이
4. 어떤 상태에서든 reset()이 원래 duration의 .stopped로 돌아옴
5. .paused에서 start()가 재개(상태가 .running이 됨)
6. 엣지 케이스: 이미 stopped일 때 reset()은 no-op
7. 엣지 케이스: 이미 paused일 때 pause()는 no-op

SettingsTests.swift의 기존 테스트 패턴을 따라.
각 테스트마다 새로운 TimerManager를 만들기 위해 setUp()을 사용해.

왜 이게 작동하나: 번호가 매겨진 수용 기준은 에이전트에게 체크리스트를 줍니다. 기존 테스트 파일을 참조하면 패턴이 정해집니다. setUp() 사용을 명시하면 에이전트가 얽힌 테스트 상태를 만드는 것을 방지합니다.

비효과적인 테스트 프롬프트:



TimerManager에 대한 테스트를 작성해.

이는 엣지 케이스를 놓치고 프로젝트의 패턴을 따르지 않을 수 있는 일반적이고 얕은 테스트를 만듭니다.

비동기 테스트 패턴

타이머 기반 및 비동기 코드 테스트:



// 안내가 잘 되었을 때 에이전트가 만드는 패턴:
final class TimerManagerTests: XCTestCase {
    var sut: TimerManager!

    @MainActor
    override func setUp() {
        super.setUp()
        sut = TimerManager()
    }

    @MainActor
    func test_start_whenStopped_transitionsToRunning() {
        // Given
        XCTAssertEqual(sut.state, .stopped)

        // When
        sut.start()

        // Then
        XCTAssertEqual(sut.state, .running)
    }

    @MainActor
    func test_timerCountsDown_afterOneSecond() async throws {
        // Given
        sut.selectedDuration = 10
        sut.reset()
        sut.start()

        // When
        try await Task.sleep(for: .seconds(1.1))

        // Then
        XCTAssertLessThanOrEqual(sut.timeRemaining, 9.0)
    }
}

에이전트가 상기시켜야 할 핵심 패턴: - @MainActor 클래스를 테스트하는 테스트 메서드에 @MainActor - Task.sleep이나 비동기 작업을 사용하는 테스트에 async throws - 시간 기반 단언에서 허용 오차(1.0초가 아니라 1.1초) - 테스트 격리를 위한 깔끔한 setUp() / tearDown()

스냅샷 테스트

시각적 회귀 검출을 위해 swift-snapshot-testing 추가를 고려하세요:



메인 타이머 뷰에 대한 스냅샷 테스트를 다음 세 가지 상태에 추가해:
1. Stopped (전체 duration 표시)
2. Running (카운트다운 표시)
3. Completed (완료 상태로 00:00 표시)

SnapshotTesting 라이브러리를 사용해. 첫 실행에서 참조 이미지를 생성해.

에이전트는 스냅샷 테스트를 올바르게 설정하지만 참조 이미지를 검토할 수는 없습니다. 당신이 초기 스냅샷을 검토하면, 그 후 에이전트의 테스트가 향후 변경에서 시각적 회귀를 잡아냅니다.


iOS 프로젝트의 컨텍스트 윈도우 관리

1M 컨텍스트 윈도우(Opus 4.7 / 4.6)는 크지만 무한하지는 않습니다. iOS 프로젝트에는 특정 컨텍스트 관리 고려사항이 있습니다.

iOS 파일의 토큰 비용

파일 타입 | 일반 크기 | 대략 토큰 수
---|---|---
SwiftUI 뷰 (단순) | 50-100 줄 | 500-1,000
SwiftUI 뷰 (복잡) | 200-400 줄 | 2,000-4,000
SwiftData 모델 | 30-80 줄 | 300-800
Manager/service 클래스 | 100-300 줄 | 1,000-3,000
Metal 셰이더 (.metal) | 50-200 줄 | 500-2,000
단위 테스트 파일 | 50-200 줄 | 500-2,000
CLAUDE.md | 100-300 줄 | 1,000-3,000
MCP 응답 (빌드) | 가변 | 200-2,000
MCP 응답 (테스트) | 가변 | 500-5,000

50개 파일 프로젝트: 모든 파일 읽기는 약 50,000-100,000 토큰을 소비 — 1M 윈도우 안에 충분히 들어갑니다. 에이전트는 전체 프로젝트를 컨텍스트에 담을 수 있습니다.

100+ 파일 프로젝트: 선택적 읽기가 필요해집니다. 에이전트가 먼저 CLAUDE.md를 읽고(파일 구조 주석을 위해), 필요한 특정 파일을 읽습니다. 이게 CLAUDE.md의 파일 주석이 결정적으로 중요한 이유입니다 — 모든 것을 읽지 않고도 에이전트를 올바른 파일로 안내합니다.

큰 프로젝트를 위한 전략

  1. 상세한 CLAUDE.md 파일 주석 — 에이전트가 파일 맵을 읽고 관련 파일로 직접 이동
  2. 서브에이전트 위임 — 탐색과 조사를 서브에이전트로 라우팅(깨끗한 컨텍스트, 요약 반환)
  3. 집중된 프롬프트 — "settings를 갱신해"보다 "SettingsView.swift를 수정해 새 토글 추가"
  4. 세션 경계 — 긴 세션을 연장하기보다 무관한 기능에 새 세션 시작
  5. /compact 사용 — Claude Code의 압축 명령은 대화를 요약하고 컨텍스트를 해제

MCP 토큰 효율성

MCP의 가장 강력한 논거 중 하나: 구조화된 JSON 응답은 raw xcodebuild 출력보다 훨씬 적은 토큰을 소비합니다.

시나리오 | Raw Bash 토큰 | MCP 토큰 | 절약
---|---|---|---
성공한 빌드 | 3,000-10,000 | 200-500 | 85-95%
실패한 빌드 (1 오류) | 3,000-10,000 | 300-800 | 90-92%
테스트 결과 (20 테스트) | 2,000-5,000 | 500-1,000 | 75-80%
시뮬레이터 목록 | 500-2,000 | 200-400 | 60-80%

빌드 사이클이 10-20번 있는 일반적 개발 세션에서 MCP는 raw xcodebuild에 비해 30,000-150,000 토큰을 절약합니다 — 실제 코드 추론에 사용 가능한 토큰입니다.


트러블슈팅

"build_sim failed — scheme not found"

에이전트가 scheme 이름을 추측하고 있습니다. 수정:



빌드하기 전에 이 프로젝트의 올바른 scheme 이름을 찾기 위해
discover_projs와 list_schemes를 사용해.

또는 CLAUDE.md에 scheme 이름을 명시하세요:



## Build
Primary scheme: `Return` (iOS)
Watch scheme: `ReturnWatch` (watchOS)
TV scheme: `ReturnTV` (tvOS)

"xcrun mcpbridge — command not found"

Xcode 26.3 이상이 필요합니다. xcodebuild -version으로 확인하세요. Xcode 26.3+가 있는데도 명령이 실패하면:



# Xcode 명령줄 도구가 선택되었는지 확인
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

# 검증
xcrun mcpbridge --help

"MCP tools not appearing in Claude Code"

세션 도중 등록된 MCP 도구는 재시작 전까지 나타나지 않을 수 있습니다. Claude Code를 종료하고 새 세션 시작:



# 현재 세션 종료 (Ctrl+C 또는 /exit)
# 새로 시작
claude

그 후 검증:



당신: XcodeBuildMCP에서 사용 가능한 모든 MCP 도구를 나열해.

"Agent keeps using xcodebuild via Bash instead of MCP"

에이전트가 Tool Search를 통해 MCP 도구를 발견하지 못하고 있습니다. 두 가지 수정:

  1. CLAUDE.md에 명시적 안내 추가 (에이전트가 MCP를 사용하도록 가르치기 참조)
  2. 직접 프롬프트: "Bash로 xcodebuild를 쓰지 말고 build_sim MCP 도구를 사용해"

"Build succeeds but agent reports failure"

XcodeBuildMCP는 xcodebuild 출력을 파싱합니다. 빌드가 오류처럼 보이는 경고를 만들면(deprecation 경고에서 흔함), 에이전트가 결과를 잘못 해석할 수 있습니다. MCP 응답의 실제 status 필드를 확인하세요.

"Simulator hangs during boot"

모든 시뮬레이터를 죽이고 재부팅:



xcrun simctl shutdown all
xcrun simctl boot "iPhone 16 Pro"

또는 에이전트에게 요청:



모든 시뮬레이터를 종료한 다음 새 iPhone 16 Pro를 부팅해.

"Agent tried to modify .pbxproj despite CLAUDE.md rules"

CLAUDE.md 규칙은 제안입니다. Hook은 강제입니다. .pbxproj 쓰기를 차단하는 PreToolUse hook이 없다면, 에이전트는 결국 시도할 것입니다. hook 설치:



{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "command": "bash -c 'INPUT=$(cat); FP=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\"); if echo \"$FP\" | grep -qE \"\\.(pbxproj|xcworkspace|xib|storyboard)$|xcodeproj/|xcworkspace/\"; then echo \"BLOCKED: Do not modify Xcode project files.\" >&2; exit 2; fi'"
      }
    ]
  }
}

규칙은 "제발 하지 마세요"라고 말합니다. Hook은 "당신은 할 수 없습니다"라고 말합니다.


FAQ

어떤 에이전트 런타임으로 시작해야 할까?

XcodeBuildMCP를 갖춘 Claude Code CLI. 가장 깊은 MCP 통합, 가장 성숙한 hook 시스템, 그리고 전체 iOS 프로젝트를 작업 메모리에 담을 수 있는 1M 컨텍스트 윈도우(Opus 4.7 / 4.6)를 가졌습니다. 여기서 시작하고, 워크플로가 성숙해지면 검토를 위한 Codex와 빠른 인라인 편집을 위한 Xcode 네이티브 에이전트를 추가하세요.

두 MCP 서버가 모두 필요한가?

대부분의 개발자에게 XcodeBuildMCP만으로 필요의 90%를 다룹니다(빌드, 테스트, 시뮬레이터, 디버깅). 문서 검색, Swift REPL 검증, SwiftUI 프리뷰 렌더링을 원한다면 Apple의 Xcode MCP를 추가하세요. 나중에 항상 추가할 수 있습니다 — 두 서버는 독립적입니다.

에이전트가 새 Xcode 프로젝트를 처음부터 만들 수 있나?

XcodeBuildMCP에는 새 Xcode 프로젝트를 스캐폴드하는 create_project 도구가 포함됩니다. 그러나 프로덕션 앱의 경우, Xcode에서 프로젝트를 생성(사이닝, capability, 타겟 구성을 올바르게 하기 위해)한 다음 모든 코드 구현에 에이전트를 사용하기를 권합니다. Xcode의 새 프로젝트 마법사에서 보내는 5분이 에이전트가 생성한 프로젝트 구성 이슈로 인한 몇 시간을 절약합니다.

에이전트가 Swift Package Manager 의존성을 어떻게 처리하나?

잘 처리합니다. Package.swift는 에이전트가 안정적으로 읽고 편집할 수 있는 표준 Swift 파일입니다. 의존성 추가, 버전 범위 갱신, 타겟 구성 모두 작동합니다. 한계는 .xcodeproj 기반 의존성 관리(Xcode의 패키지 해결 UI)입니다 — 그것은 Xcode가 관리하며 에이전트가 편집해서는 안 됩니다.

에이전트가 App Store에 제출할 수 있나?

아니요. App Store 제출은 Xcode의 Organizer, 프로비저닝 프로파일, 스크린샷, 메타데이터, App Store Connect 포털을 포함합니다. 이 중 어느 것도 에이전트가 의미 있게 운영할 수 있는 방식으로 MCP나 명령줄 도구를 통해 접근할 수 없습니다. 에이전트는 아카이브까지 모든 것을 처리합니다 — 구현, 테스트, 버그 수정, 문서화. 제출의 마지막 단계는 사람의 일로 남아 있습니다.

다만 에이전트는 App Store 메타데이터에 도움이 됩니다. 최신 변경에 기반해 앱 설명, 키워드, what's-new 텍스트를 작성해 달라고 에이전트에 요청하세요. 이것은 에이전트가 탁월한 텍스트 생성 작업입니다.

에이전트 보조 iOS 개발에서 secrets와 API 키를 어떻게 처리하나?

절대 secrets를 커밋하지 마세요. 백엔드 API에 연결하는 iOS 앱의 경우:

  1. 환경별 구성에 .xcconfig 파일 사용
  2. .xcconfig 파일을 .gitignore에 추가
  3. Info.plist 빌드 설정을 통해 config 값 참조
  4. 실제 값을 포함하지 않고 필요한 secrets를 CLAUDE.md에 문서화


## Configuration

API base URL and keys are in `Config.xcconfig` (not committed).
Required keys:
- `API_BASE_URL` — Backend server URL
- `API_KEY` — Authentication token

Create `Config.xcconfig` from `Config.xcconfig.template`.

에이전트는 키가 존재하고 어디에 사용되는지 알지만 실제 값은 절대 보지 않습니다.

SwiftUI 애니메이션 — 에이전트가 작성할 수 있나?

에이전트는 문법적으로 애니메이션 코드를 잘 작성하지만 결과를 시각적으로 검증할 수 없습니다. 단순 애니메이션(.animation(.spring()), .transition(.slide), withAnimation { })은 올바른 결과를 만듭니다. 정밀한 타이밍이 있는 복잡한 다단계 애니메이션은 에이전트가 할 수 없는 시각적 반복이 필요합니다.

효과적: "타이머가 상태 사이를 전이할 때 스프링 애니메이션을 추가해."

비효과적: "타이머 애니메이션이 만족스럽게 느껴지게 만들어." (주관적, 시각적 튜닝 필요.)

에이전트가 오류 처리 패턴을 어떻게 처리하나?

매우 잘. 에이전트는 Swift의 do/catch, Result, async throws 패턴을 이해합니다:



HealthKit 권한 흐름에 대한 오류 처리를 구현해:
1. HKHealthStore.isHealthDataAvailable() 확인 — 아니면 알림 표시
2. 권한 요청 — 거부를 우아하게 처리
3. 쓰기 실패 시 — 한 번 재시도, 그 후 오류 표시
4. 모든 오류는 지역화된 설명과 함께 사용자에게 노출되어야 함

에이전트는 적절한 사용자 노출 메시지가 있는 구조화된 오류 처리를 만듭니다. 가끔 오류를 과도하게 처리합니다(전파되어야 할 예외를 잡음), 그러므로 catch 블록을 검토하세요.

접근성 구현에 에이전트를 사용할 수 있나?

부분적으로. 에이전트는 접근성 라벨, 힌트, trait를 올바르게 추가합니다:



TimerView의 모든 상호작용 요소에 접근성 라벨을 추가해:
- 타이머 디스플레이: 현재 남은 시간
- 시작/일시정지 버튼: 현재 상태와 액션
- 리셋 버튼: "Reset timer"
- Duration 피커: 선택된 duration

에이전트가 할 수 없는 것: VoiceOver 내비게이션 순서가 올바른지 검증, Dynamic Type 스케일링 테스트, 색상 대비 비율 평가. 검증에는 Xcode의 Accessibility Inspector를 사용하세요.

에이전트가 Core Data 마이그레이션을 어떻게 처리하나(SwiftData를 사용하지 않을 때)?

에이전트는 Core Data 마이그레이션 매핑과 모델 버전을 작성하지만, 수동 Xcode 단계(새 모델 버전 생성, 현재 버전 선택)는 자동화할 수 없습니다. 여전히 SwiftData가 아닌 Core Data를 사용한다면 모델 버전 히스토리를 CLAUDE.md에 문서화하세요:



## Core Data Model Versions
- V1: Initial (GroceryList, GroceryItem)
- V2: Added Category model (current)
- Migration: Lightweight automatic for V1→V2

에이전트가 SwiftUI 프리뷰를 어떻게 처리하나?

두 가지 방법: 1. Apple Xcode MCP의 RenderPreview 도구 가 프리뷰를 헤드리스로 렌더링하고 결과를 반환합니다. 에이전트가 프리뷰가 오류 없이 컴파일되고 렌더링되는지 검증할 수 있지만, 시각적 정확성은 평가할 수 없습니다. 2. 빌드 기반 검증build_sim은 프리뷰 프로바이더가 컴파일됨을 확인합니다. 프리뷰가 런타임에 크래시하면 빌드는 여전히 성공합니다 — Xcode가 프리뷰 렌더링을 시도할 때만 크래시가 나타납니다.

프리뷰의 시각적 검증을 위해서는 여전히 Xcode를 열어야 합니다.

visionOS와 Apple Vision Pro는 어떤가?

같은 패턴이 적용됩니다. XcodeBuildMCP는 visionOS 시뮬레이터를 지원하며, 아키텍처 패턴(@Observable, NavigationStack, SwiftData)은 동일합니다. RealityKit 전용 코드(3D 콘텐츠, 몰입형 공간, 핸드 트래킹)는 Metal과 같은 한계를 따릅니다 — 에이전트는 올바른 코드를 작성할 수 있지만 공간적 출력을 검증할 수 없습니다.

에이전트가 어려워하기 시작할 정도로 프로젝트가 얼마나 커질 수 있나?

컨텍스트 윈도우 크기가 한계 요인입니다. Opus 4.6의 1M 토큰 윈도우로, Claude Code는 동시에 활성 작업 메모리에 약 50-70개의 Swift 파일을 담을 수 있습니다. 더 큰 프로젝트의 경우, 에이전트가 코드베이스의 부분집합으로 작업하기 위해 파일 검색과 선택적 읽기를 사용합니다. 100+ 파일 프로젝트는 잘 작동합니다 — 에이전트가 모든 것을 컨텍스트에 담는 게 아니라 필요할 때 파일을 읽을 뿐입니다.

실용적 한계는 파일 수가 아니라 코드베이스 일관성입니다. 잘 문서화된 200개 파일 프로젝트가 문서화되지 않은 30개 파일 프로젝트보다 더 좋은 결과를 만듭니다.

iOS 개발에 에이전트를 사용하려면 Swift를 알아야 하나?

에이전트 출력을 검토하고 아키텍처적 결정을 내릴 수 있어야 합니다. 모든 줄을 직접 작성할 필요는 없지만, 에이전트가 잘못된 선택을 할 때 — 특히 동시성, 메모리 관리, 프레임워크별 패턴 — 잡을 만큼 Swift를 잘 이해해야 합니다. 에이전트는 기존 기술의 10배 증폭기이지 그것의 대체재가 아닙니다.

에이전트가 Swift 파일의 머지 충돌을 어떻게 처리하나?

에이전트는 Swift 소스 파일의 머지 충돌을 안정적으로 해결합니다. 표준 충돌 마커(<<<<<<<, =======, >>>>>>>)는 모든 에이전트 런타임이 잘 이해합니다. 그러나 .pbxproj 파일의 머지 충돌은 수동 해결 작업으로 남아 있습니다 — 에이전트에게 .pbxproj 충돌 해결을 요청하지 마세요.

iOS 개발에 에이전트를 운영하는 비용은?

Anthropic의 Max 플랜(기본 Opus 4.7, 표준 가격에 1M 컨텍스트)으로, 일반적인 iOS 개발 세션은 30-120분 운영하며 200K-800K 토큰을 처리합니다. MCP 도구 호출은 최소한의 오버헤드를 더합니다(구조화된 JSON 응답은 raw 빌드 출력에 비해 토큰 효율적). 비용은 다른 코드베이스에 Claude Code를 운영하는 것과 비교 가능합니다 — iOS 개발은 의미 있게 웹 개발보다 더 비싸거나 싸지 않습니다.

UIKit 프로젝트에 에이전트를 사용할 수 있나?

예, 그러나 에이전트는 SwiftUI에서 더 효과적입니다. UIKit은 더 많은 보일러플레이트를 요구하며, 선언적 구조가 적고, 종종 에이전트가 편집할 수 없는 Interface Builder 파일을 포함합니다. UIKit 프로젝트가 있다면 모델 계층과 비즈니스 로직에는 에이전트를 사용하면서 UI는 수동으로 처리하거나, 점진적으로 뷰를 SwiftUI로 마이그레이션하는 것을 고려하세요.

에이전트가 지역화를 어떻게 처리하나?

에이전트는 .xcstrings(Xcode 문자열 카탈로그) 파일을 효과적으로 만들고 편집합니다. 새 지역화 키를 추가하고, 번역을 제공하고, 언어 전반에 걸쳐 일관성을 유지할 수 있습니다. .xcstrings 파일의 구조화된 JSON 포맷은 에이전트 친화적입니다. .strings 파일(레거시 포맷)에서도 에이전트가 잘 수행합니다 — key-value 포맷은 직관적입니다.


iOS에서 흔한 에이전트 실수 (그리고 방지법)

8개 iOS 프로젝트에서 수천 번의 에이전트 상호작용을 통해 관찰한 반복적 오류들입니다. 각각에 방지 전략이 있습니다.

실수 1: Observable 패턴 혼합

일어나는 일: 에이전트가 한 파일에서는 @Observable을, 다른 파일에서는 ObservableObject를 사용하거나, 이미 Observable인 @Model 클래스에 @Observable을 추가합니다.

방지: CLAUDE.md의 명시적 규칙:



- NEVER use ObservableObject — use @Observable
- NEVER add @Observable to @Model classes (already Observable)
- NEVER use @StateObject — use @State with @Observable
- NEVER use @ObservedObject — access @Observable properties directly

실수 2: 클로저에서 Retain Cycle 만들기

일어나는 일: 에이전트가 self를 강하게 캡처하는 클로저를 만듭니다. 특히 Timer.publish, NotificationCenter, completion handler에서.

방지: CLAUDE.md에 클로저 패턴 포함:



## Closure Pattern
- Timer callbacks: use `[weak self]` and guard
- NotificationCenter observers: store in `Set<AnyCancellable>` and use `[weak self]`
- Completion handlers: use `[weak self]` for any closure stored beyond the call site

실수 3: @MainActor 요구사항 무시

일어나는 일: 에이전트가 @MainActor isolation 없이 @Observable 클래스를 만들어, UI 갱신이 메인 스레드 외부에서 일어날 때 Swift 6.2 동시성 경고나 런타임 크래시를 일으킵니다.

방지:



## Concurrency Rule
ALL @Observable classes MUST be @MainActor:
@Observable
@MainActor
final class SomeManager { }

실수 4: Destination Closure가 있는 NavigationLink 사용

일어나는 일: 에이전트가 타입 안전 NavigationLink(value:) + .navigationDestination(for:) 패턴 대신 deprecated된 NavigationLink(destination:label:)을 사용합니다.

방지:



## Navigation Pattern
ALWAYS use value-based navigation:
NavigationLink(value: item) { ItemRow(item: item) }
.navigationDestination(for: Item.self) { ItemDetailView(item: $0) }

NEVER use: `NavigationLink(destination: ItemDetailView(item: item)) { }`

실수 5: 시뮬레이터 이름 하드코딩

일어나는 일: 에이전트가 시스템에 존재하지 않을 수 있는 특정 시뮬레이터 이름("iPhone 16 Pro")으로 빌드 명령을 작성합니다.

방지: MCP가 이를 처리합니다 — list_sims가 사용 가능한 시뮬레이터를 발견합니다. CLAUDE.md에:



## Simulators
Do NOT hardcode simulator names. Use `list_sims` MCP tool to discover
available devices, then `boot_sim` with the discovered device ID.

실수 6: 잘못된 디렉터리에 파일 생성

일어나는 일: 에이전트가 Views/ 하위 디렉터리 대신 프로젝트 루트에 새 뷰 파일을 만들거나, 모델을 잘못된 그룹에 둡니다.

방지: CLAUDE.md의 파일 구조 주석이 배치를 안내합니다. 추가로:



## File Placement Rules
- Views → `AppName/Views/`
- Models → `AppName/Models/`
- Managers → `AppName/Managers/`
- Extensions → `AppName/Extensions/`
- Tests → `AppNameTests/`

실수 7: 플랫폼 가용성을 처리하지 않음

일어나는 일: 에이전트가 tvOS(HealthKit이 사용 불가)에서 컴파일되는 공유 코드에서 HealthKit을 사용하거나, watchOS 코드에서 ActivityKit을 사용합니다.

방지:



## Platform Guards
- HealthKit: `#if canImport(HealthKit)` (unavailable on tvOS)
- ActivityKit: `#if canImport(ActivityKit)` (iOS only)
- WatchKit: `#if os(watchOS)`
- UIKit haptics: `#if os(iOS)` (unavailable on tvOS, watchOS uses WKHaptic)

실수 8: 단순 기능을 과잉 엔지니어링

일어나는 일: 에이전트가 20줄짜리 유틸리티 함수가 되어야 할 것을 위해 프로토콜, 프로토콜 익스텐션, 구체 구현, 팩토리, 의존성 주입 컨테이너를 만듭니다.

방지: 단순성 원칙을 포함:



## Architecture Principle
Prefer the simplest solution that handles the requirements.
- Direct implementation over protocol abstraction (unless you have 2+ conforming types)
- Concrete types over generics (unless reuse is proven)
- Extensions on existing types over new wrapper types


솔직한 평가

AI 에이전트로 8개의 iOS 앱을 출시한 후의 요약입니다:

에이전트가 변혁한 것: 구현 속도. 며칠 걸리던 게 몇 시간 걸립니다. SwiftUI 뷰, SwiftData 모델, 단위 테스트, 리팩터링 — 이것들은 이제 주로 에이전트가 만들고 사람이 검토합니다.

에이전트가 변혁하지 않은 것: 아키텍처적 결정, 시각 디자인, 성능 최적화, App Store 제출. 이것들은 사람 주도로 남아 있습니다.

증폭은 실재하지만 한계가 있습니다. 적절한 MCP와 hook 구성이 있는 잘 문서화된 프로젝트에서 3-5배 생산성 향상으로 추정합니다. hook이 없는 문서화되지 않은 프로젝트는 1.5-2배 향상 정도를 봅니다 — 에이전트가 빌드하기보다 추측에 너무 많은 시간을 소비합니다.

보상받는 투자: CLAUDE.md, hook, MCP 구성에 들이는 시간. 모든 시간의 설정은 에이전트 실수를 바로잡는 많은 시간을 절약합니다. 구성이 곧 제품입니다 — 에이전트는 실행 엔진입니다.

저를 놀라게 한 것: MCP 서버가 역학을 얼마나 바꿨는지. MCP 이전에 에이전트는 Swift를 이해하는 정교한 텍스트 편집기였습니다. MCP 이후에 그들은 작성하고, 빌드하고, 테스트하고, 디버그하고, 반복하는 개발 파트너입니다. 구조화된 피드백 루프는 코드를 작성하는 에이전트와 코드를 출시하는 에이전트의 차이입니다.

과거의 저에게 해줄 말: 가장 작은 앱(Reps, 14파일)으로 시작하고, MCP와 hook 설정을 올바르게 하고, 철저한 CLAUDE.md를 작성한 다음, 패턴을 더 큰 프로젝트로 확장하세요. 63파일 멀티플랫폼 앱으로 시작하지 마세요. 인프라 투자는 프로젝트 크기와 무관하게 동일합니다 — 작은 프로젝트에서 한 번 하고, 그 후 모든 것에 복사하세요.

미래: Xcode 26.3의 네이티브 에이전트 통합은 시작이지 끝이 아닙니다. Apple이 MCP 지원을 출시한 것은 툴체인이 에이전트 우선 개발로 움직이고 있다는 뜻입니다. 지금 에이전트 호환 프로젝트 구조 — 깨끗한 CLAUDE.md 파일, 테스트 가능한 아키텍처, 자동화된 hook — 에 투자하는 개발자들은 도구가 개선됨에 따라 그 투자가 복리로 불어날 것입니다.


빠른 참조 카드

설치 (1회 설정)



# XcodeBuildMCP (59 도구)
claude mcp add XcodeBuildMCP -s user \
  -e XCODEBUILDMCP_SENTRY_DISABLED=true \
  -- npx -y xcodebuildmcp@latest mcp

# Apple Xcode MCP (20 도구)
claude mcp add --transport stdio xcode -s user -- xcrun mcpbridge

# Codex MCP 설정
codex mcp add xcode -- xcrun mcpbridge

# 검증
claude mcp list

필수 CLAUDE.md 섹션



1. 프로젝트 정체성 (bundle ID, target OS, 아키텍처)
2. 주석이 달린 파일 구조
3. 빌드 및 테스트 명령
4. 핵심 패턴과 규칙
5. 금지 (.pbxproj 절대 건드리지 않음)
6. 프레임워크별 컨텍스트

필수 Hook



{
  "PreToolUse": [{ "matcher": "Edit|Write", "command": "block .pbxproj" }],
  "PostToolUse": [{ "matcher": "Edit|Write", "command": "swiftformat" }]
}

아키텍처 규칙



@Observable         (ObservableObject 안 됨)
NavigationStack     (NavigationView 안 됨)
@State              (@StateObject 안 됨)
SwiftData @Model    (Core Data 안 됨)
async/await         (completion handler 안 됨)
@MainActor          (모든 Observable 클래스에)
.glassEffect()      (Liquid Glass, iOS 26+)

MCP 도구 우선순위



Build:     build_sim          (Bash로 xcodebuild 안 됨)
Test:      test_sim           (Bash로 xcodebuild test 안 됨)
Sim:       list_sims/boot_sim (Bash로 xcrun simctl 안 됨)
Docs:      DocumentationSearch (WebSearch 안 됨)
REPL:      ExecuteSnippet     (Bash로 swift 안 됨)


변경 로그

날짜 | 변경
---|---
2026-04-13 | 초판 발행. 8개 앱, 3개 런타임, MCP 설정, CLAUDE.md 패턴, hook, 케이스 스터디.


참고문헌


  1. XcodeBuildMCP는 기본적으로 Sentry 텔레메트리를 포함합니다. 프로젝트의 개인정보 문서는 무엇이 전송되는지 자세히 다룹니다: 오류 메시지, 스택 트레이스, 일부 경우 파일 경로. XCODEBUILDMCP_SENTRY_DISABLED=true 환경 변수가 완전히 옵트아웃합니다. ↩

  2. Anthropic, "Model Context Protocol Specification," modelcontextprotocol.io/specification. MCP 명세는 XcodeBuildMCP와 Apple의 Xcode MCP가 모두 구현하는 JSON-RPC 전송, 도구 발견, 리소스 프로토콜을 정의합니다. ↩

  3. XcodeBuildMCP, github.com/getsentry/XcodeBuildMCP. 오픈 소스, Sentry가 유지보수. 시뮬레이터, 디바이스, 디버깅, UI 자동화 워크플로에 걸쳐 59개 도구. 변경 로그가 있는 시맨틱 버저닝. ↩

  4. Apple은 Xcode 26.3 지능형 개발자 도구 이니셔티브의 일환으로 Xcode MCP 서버를 도입했으며, MCP를 AI 코딩 어시스턴트와 Xcode 툴체인 사이의 인터페이스 계층으로 자리매김했습니다. 공식 문서는 Xcode 릴리스 노트 참조. ↩

  5. Rudrank Riyam, "Exploring Xcode Using MCP Tools," rudrank.com/exploring-xcode-using-mcp-tools-cursor-external-clients, 2026. Apple의 MCP 도구 수, XPC 의존성, 문서 검색 기능에 대한 독립적 확인. ↩

  6. Jimenez, C.E., Yang, J., Wettig, A., et al., "SWE-bench: Can Language Models Resolve Real-World GitHub Issues?" ICLR 2024. arxiv.org/abs/2310.06770. 구조화된 도구 접근을 가진 에이전트가 비구조화 셸 명령에 제한된 에이전트를 크게 능가했습니다. 이 발견은 에이전트 효율성을 위한 구조화된 MCP 인터페이스를 검증합니다. ↩

  7. Claude Code CLI 문서, code.claude.com. Hook 시스템, MCP 구성, 서브에이전트 위임, 에이전트 정의. ↩

  8. SwiftFormat, github.com/nicklockwood/SwiftFormat. 일관된 코드 스타일을 위해 PostToolUse hook에서 사용되는 Swift 포매팅 도구. ↩

  9. XcodeBuildMCP 공식 사이트, xcodebuildmcp.com. CLI 출력 예시를 통해 59개 MCP 도구를 확인. 도구 카테고리: 시뮬레이터, 디바이스, 디버깅, UI 자동화. Homebrew 또는 npx를 통해 설치. ↩

  10. Swiftjective-C, "Agentic Coding in Xcode 26.3 with Claude Code and Codex," swiftjectivec.com, 2026년 2월. Xcode 26.3이 Settings > Intelligence를 통해 네이티브 Claude Agent와 Codex 런타임 지원과 함께 출시됨을 확인. xcrun mcpbridge를 통해 노출된 20개 MCP 도구. ↩

  11. Blake Crosley, "Two MCP Servers Made Claude Code an iOS Build System," blakecrosley.com/blog/xcode-mcp-claude-code, 2026년 2월. 같은 저자의 iOS 개발 워크플로에서의 설정 가이드와 실세계 결과. ↩