Xcode Internals: 내부에 숨겨진 파일들 - BoostSwiftUI/SwiftUI GitHub Wiki

이 세션은 Xcode 26을 기준으로 Xcode의 내부 동작 원리와 개발 환경을 심층적으로 분석하는 기술 발표입니다

Xcode 실행 과정

애플리케이션 실행 메커니즘

Xcode를 클릭하여 실행하면 Finder가 Xcode.app 디렉토리 내 Contents 번들 구조를 열어 Info.plist를 확인하고 실행 파일을 찾아 실행합니다. 이는 터미널에서 바이너리 파일을 직접 실행하는 것과 동일하지만, 번들 구조를 통해 다양한 바이너리와 리소스를 묶어서 활용합니다.

Xcode 번들 구조

Xcode 번들은 크게 5가지 구성요소로 나뉩니다:

  • 확장 프로그램들 (Instruments 등)
  • SDK와 플랫폼별 도구들
  • 개발자 도구 및 명령어들
  • 프레임워크들 (Apple 전용 private 프레임워크 포함)
  • 플러그인들

가장 많이 사용되는 것은 Contents/Developer/usr/bin 아래의 CLI 도구들입니다. Git, 차이점 도구들도 함께 배포되어 Xcode 버전에 맞는 도구들을 사용할 수 있습니다.

프로세스 실행 구조

macOS에서는 launchd가 PID 1번으로 최상위 프로세스 역할을 하며, 모든 애플리케이션을 실행시킵니다. Darwin에서는 Unix/Linux의 fork-exec 방식 대신 POSIX spawn 시스템 콜을 사용하여 한 번에 자식 프로세스를 생성합니다.

개발 환경 구성

라이브러리 및 데이터 저장소

각 계정의 ~/Library/Developer 폴더에는 다음과 같은 데이터가 저장됩니다:

  • CoreSimulator: 시뮬레이터 데이터 (Xcode 버전별로 누적되어 10GB 이상 차지)
  • DerivedData: 빌드 결과물
  • Toolchains: Swift 버전별 체인
  • TestDevices: 테스트 디바이스 정보
  • DeveloperImages: 디바이스 복원용 디스크 이미지

용량 부족 시 Caches 폴더부터 정리하는 것이 효과적입니다.

Xcode-select 도구

여러 Xcode 버전을 관리할 수 있는 명령어로, xcode-select --install로 필수 커맨드라인 도구만 설치할 수 있습니다. Git 등의 도구도 함께 설치됩니다.

Coding Intelligence (Xcode 26)

Xcode 26에는 AI 기반 코딩 지원 기능이 포함되어 있으며, 플러그인 내부에 SwiftUI, 코드 변경 등 상황별 프롬프트 템플릿이 텍스트 문서로 저장되어 있습니다. 이를 참고하여 더 상세한 프롬프트를 작성할 수 있습니다.

인덱싱 시스템

인덱스 생성 과정

Xcode는 프로젝트 로딩 시 빌드 전에 먼저 인덱스를 생성합니다. 이는 소스 코드의 심볼들과 참조 관계를 분석하여 데이터베이스를 만드는 과정으로, DerivedData 프로젝트별 .noindex 폴더에 저장됩니다.

IndexStore-DB

Apple GitHub 저장소에 공개된 오픈소스로, Objective-C, Swift가 공통으로 사용하는 메모리 DB입니다. Swift 컴파일러가 인덱스 생성 시 약 3%의 오버헤드가 발생합니다.

SourceKit 서비스

Swift Syntax 라이브러리를 기반으로 구현된 서비스 데몬으로, Xcode 실행 시 자동으로 시작되어 LSP를 통해 자동완성, 문법 검사 등을 제공합니다. 인덱싱이 제대로 되지 않으면 syntax highlighting이 깨지거나 빨간색 오류 표시가 나타나지 않습니다.

인덱싱 문제점

  • 중단할 수 없는 자동 동작
  • 브랜치 변경 시 이전 정보가 남아있어 혼란 발생
  • 메모리 DB 특성상 메모리 부족 시 문제 지속
  • 해결책: Xcode 재시작 또는 DerivedData 폴더 삭제

빌드 시스템

빌드 과정

Swift 빌드는 전통적인 C/C++ 빌드와 다르게 Swift 코드를 직접 오브젝트 파일로 변환하거나 LLVM 어셈블리 파일을 거쳐 빌드할 수 있습니다. 최근에는 swiftc 대신 swift-frontend가 컴파일러, 어셈블러, 백엔드 역할을 통합하여 처리합니다.

빌드 구성요소

  • Build Phases: 위에서 아래로 순차 실행 (의존성 → 컴파일 → 링크 → 번들 복사)
  • Build Rules: 파일 확장자별 처리 규칙 (PNG 압축 등)
  • Build Settings: 우선순위는 오른쪽에서 왼쪽 (iOS Default → 프로젝트 → 타겟)

Swift Package 관리

Swift Package는 DerivedData 아래 SourcePackages에서 별도로 빌드되며, 저장소 복사 후 체크아웃하여 빌드합니다. 패키지 정보는 컬렉션 DB로 캐싱되어 업데이트 문제 시 DB 갱신이 필요할 수 있습니다.

증분 빌드

인터페이스 해시를 기반으로 의존성을 관리하여, 인터페이스 변경 시에만 의존 파일들을 재빌드합니다. 내부 구현 변경은 해당 파일만 빌드 후 링크합니다.

실행 및 디버깅

macOS 앱 실행

  • Release 모드: launchd가 직접 실행 (Xcode 관여 없음)
  • Debug 모드: Xcode → LLDB 서버 → 디버그 서버 → 앱 (3단계 구조로 원격 디버깅 지원)

iOS 시뮬레이터 실행

시뮬레이터가 앱을 실행하는 것이 아니라, 앱이 시뮬레이터 API를 사용하여 화면을 그립니다. 시뮬레이터는 Xcode가 아닌 launchctl 명령으로 launchd가 실행합니다.

디바이스 실행

디버그 서버가 소켓을 통해 원격으로 iPhone의 앱을 실행시키는 구조입니다. 디버거 세션이 끊어지면 소켓 연결 오류가 발생할 수 있습니다.

테스팅 시스템

XCTest 구조

테스팅 타겟에서 Host Application 지정 여부에 따라 실행 방식이 달라집니다:

  • Host Application 지정: 호스트 앱이 디버거로 실행되어 앱과 동일한 환경에서 테스트
  • Host Application 미지정: XCTest 실행 파일이 테스트 코드를 직접 실행

권한 차이

macOS에서는 Host Application 지정 여부에 따라 샌드박스 권한이 달라집니다. XCTest로 실행 시 더 많은 시스템 폴더에 접근 가능하여 테스트 결과가 달라질 수 있습니다.

Swift Testing

Swift Testing은 매크로를 통해 XCTest로 변환되므로, Host Application을 None으로 설정해도 XCTest가 실행됩니다.

결론 및 개선 요청

Xcode는 점점 복잡해지고 많은 서브 프로세스들이 각각의 서비스를 담당하고 있습니다. 페이스 빌더, Swift Package, SourceKit 등 숨겨진 서비스들이 다양한 기능을 제공하지만, 이로 인해 Xcode가 무거워지고 크래시가 빈번해지는 문제가 있습니다.

발표자는 Xcode가 여전히 App Store에서 별점이 낮은 앱 중 하나이며, Apple의 우선순위에서 밀려난 것 같다고 지적했습니다. 개발자들을 위해 더 안정적이고 가벼운 디버깅 전용 Xcode의 필요성을 제기하며 발표를 마무리했습니다.