RSS듀오랩스
개발 도구

xcode-select와 DEVELOPER_DIR: 어느 쪽이 정석일까?

작성자
듀오랩스 대표·7분 읽기

Expo 앱을 iOS 시뮬레이터에 띄우려고 도구부터 점검했는데, 결과가 앞뒤가 안 맞았습니다.

$ xcodebuild -version
xcodebuild: error: ...

$ swift --version
Apple Swift version 6.3.3 (swiftlang-6.3.3.1.3)

Swift 컴파일러는 6.3.3 이 멀쩡히 답하는데 xcodebuild 는 없다고 합니다. 시뮬레이터 목록을 뽑으려 하니 더 이상했습니다.

$ xcrun simctl list devices
xcrun: error: unable to find utility "simctl", not a developer tool or in PATH

/Applications/Xcode.app 은 자리에 그대로 있었습니다. 버전을 직접 읽어 보니 26.6, 빌드 17F113 이었습니다.

Xcode 를 안 보고 있던 활성 개발자 디렉터리

원인은 한 줄로 나왔습니다.

$ xcode-select -p
/Library/Developer/CommandLineTools

macOS 에는 "지금 활성인 개발자 디렉터리" 라는 전역 설정이 하나 있고, xcrunxcodebuild 는 전부 그 값을 보고 도구를 찾습니다. 그 값이 Command Line Tools 를 가리키고 있었습니다. CLT 에도 clang, swift, git 은 들어 있습니다. 그래서 컴파일러는 답했습니다. 반면 simctl, xcodebuild, 시뮬레이터 런타임은 Xcode.app 안에만 있습니다. 그래서 그쪽만 통째로 없었습니다.

Xcode 를 안 깐 것도 아니고 깨진 것도 아니었습니다. 가리키는 곳이 틀렸을 뿐입니다. 보통 Xcode 를 먼저 깔고 나중에 CLT 를 따로 설치하면 이 상태가 됩니다.

전역 설정을 피하려던 처음 판단

고치는 방법이 둘이라는 건 금방 알았습니다.

# 1. 전역 전환
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

# 2. 명령 단위 우회
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer npx expo run:ios

저는 2번을 골랐습니다. sudo 가 붙는 게 마음에 걸렸고, 전역 설정을 바꾸면 다른 프로젝트에도 영향이 간다는 게 부담스러웠습니다. 부작용이 작은 쪽이 안전하다고 생각했습니다.

고르고 나서 뒤늦게 의문이 들었습니다. 부작용이 작다는 것과 옳다는 것은 다른 이야기입니다.

거꾸로 읽고 있던 "영향이 간다"

다시 보니 제 판단의 전제가 틀렸습니다.

전역 전환이 다른 프로젝트에 영향을 주는 건 맞습니다. 그런데 그 영향이 정상 방향입니다. 지금 상태에서는 이 머신의 어떤 프로젝트도 시뮬레이터를 못 씁니다. Flutter 를 깔아도, 다른 회사 앱을 클론해도 똑같이 simctl 을 못 찾습니다. 전환은 그걸 고치는 것이지 망가뜨리는 게 아닙니다.

제가 "부작용" 이라고 부른 것은 사실 "복구" 였습니다. 지키려던 상태가 애초에 정상이 아니었는데, 건드리지 않는 쪽을 보수적이라고 착각했습니다.

여기에 더해 우회는 비용이 계속 듭니다. DEVELOPER_DIR 은 환경변수라서 그 명령, 그 셸, 그 서브프로세스에만 붙습니다. 다음에 터미널을 새로 열고 npx expo run:ios 를 치면 그대로 실패합니다. Xcode 를 GUI 로 열어 쓰는 순간에도 안 따라갑니다. 그리고 실패했을 때 나오는 메시지는 방금 제가 본 그 "not a developer tool" 이라, 원인을 다시 처음부터 찾게 됩니다.

정석은 도구들이 전제하는 쪽

결정적인 근거는 생태계 쪽에 있었습니다. Expo, React Native, Flutter, Fastlane 문서가 하나같이 xcode-select -p 가 Xcode 를 가리킨다고 가정하고 쓰여 있습니다. 뭔가 안 될 때 그 도구들이 뱉는 안내문도 전부 xcode-select -s 를 실행하라고 합니다. 우회로 굴러가는 환경은 그 안내문과 계속 어긋납니다.

DEVELOPER_DIR 이 쓸모없다는 뜻은 아닙니다. 정당한 자리가 따로 있습니다.

xcode-select -s DEVELOPER_DIR
적용 범위 머신 전체, 영구 그 명령 하나
권한 sudo 필요 불필요
쓰는 자리 평소 개발 머신의 기본 상태 Xcode 여러 버전 중 하나를 고정할 때, CI 처럼 전역 상태를 안 건드리는 게 원칙인 환경

우선순위는 DEVELOPER_DIR 이 높습니다. 그래서 CI 에서 Xcode 16 과 26 을 오가며 빌드할 때는 이쪽이 정확한 도구입니다. 제 경우는 Xcode 가 한 벌뿐이었으니 해당이 없었습니다. 예외 상황용 도구를 기본 상태에 쓰려 했던 셈입니다.

전환한 뒤

한 줄로 끝났습니다.

$ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
$ xcodebuild -version
Xcode 26.6
Build version 17F113

시뮬레이터는 11대가 잡혔고 iOS 26.5 런타임도 그때서야 보였습니다. CocoaPods 를 brew install cocoapods 로 1.17.0 을 깔고 npx expo prebuild --platform ios 를 돌리니 ios/ 생성과 Pod 설치까지 한 번에 지나갔습니다.

참고로 이 앱은 MapLibre 를 쓰는 터라 Expo Go 로는 아예 안 뜹니다. 네이티브 모듈이 들어간 앱은 dev client 를 직접 빌드해야 하고, 그래서 시뮬레이터가 없으면 화면을 볼 방법 자체가 없었습니다. xcode-select 한 줄이 막고 있던 게 그것이었습니다.

한 줄로 끝나는 원복

전역 설정이라 겁이 났던 것치고 원복은 간단합니다.

sudo xcode-select -s /Library/Developer/CommandLineTools

xcode-select 가 하는 일은 /var/db/xcode_select_link 심볼릭 링크를 바꾸는 것뿐입니다. 되돌릴 수 없는 변경을 피하려는 신중함은 좋지만, 그 변경이 실제로 되돌릴 수 있는지부터 확인했어야 했습니다. 저는 그걸 안 보고 우회부터 골랐습니다.

한 가지는 아직 확인 못 했습니다. Xcode 를 여러 버전 깔아 두고 프로젝트마다 다른 버전을 써야 하는 상황이라면 전역 전환만으로는 부족할 텐데, 그때 .envrc 같은 걸로 디렉터리 단위 DEVELOPER_DIR 을 거는 게 실제로 편한지는 안 써 봐서 모르겠습니다.

이 게시글 공유하기

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.