Joyuno's Dev Blog

2026-08-09 (일) 개발일지

dev-blog

오늘은 lepons를 macOS(arm64)에서 직접 빌드해서 로컬 실행까지 끌어올리는 작업을 했다. 프로젝트가 Windows/Linux 기준으로 개발돼 있어서 macOS에선 제품 결함이 아닌 환경 이슈로 테스트가 실패하는 경우가 꽤 있었다. 그중 특히 두 개를 오래 붙들었다. 하나는 조종석(cockpit)의 로컬 PTY 세션이 posix_spawnp failed로 죽는 문제였고, 다른 하나는 Claude Code CLI의 effort 설정이 picker에 안 나타나는 문제였다. 결론적으로 둘 다 에러 메시지를 곧이곧대로 읽으면 계속 헛도는 유형이었다.

lepons 조종석 로컬 세션 — posix_spawnp failed의 두 원인

증상은 간단했다. Electron 기반 조종석 앱에서 로컬 세션을 열면 posix_spawnp failed 에러가 나면서 터미널이 즉시 닫혔다. Electron 로그에는 실패 코드만 있고 어떤 파일이 문제인지는 전혀 안 나왔다.

첫 번째 의심은 macOS 특유의 경로 처리였다. macOS는 /tmp가 /private/tmp로, /var가 /private/var로 연결되는 심볼릭 링크 구조를 갖고 있어서, TMPDIR이 링크 경로를 그대로 들고 있으면 프로세스가 헬퍼를 찾지 못하는 경우가 있다. 그래서 TMPDIR을 canonical 경로(/private/var/...)로 바꿔 전체 테스트를 돌렸고, 실제로 이 변경으로 일부 테스트가 통과했다. 원인을 잡았다고 생각했다.

그런데 조종석 앱의 실제 PTY 세션은 여전히 같은 에러로 죽었다. 테스트가 통과했는데 앱이 실패한다는 건, 내가 잡은 게 전체 원인이 아니라 원인 중 하나라는 뜻이었다. 이번엔 node_modules/node-pty를 직접 뜯어봤다. node-pty는 로컬 PTY를 만들 때 spawn-helper라는 헬퍼 바이너리를 쓰는데, 이 파일의 권한이 아래처럼 풀려 있었다.

-rw-r--r--  1 user staff  23984 .../spawn-helper

실행 비트가 없다. node-pty 1.1.0의 npm 패키징이 spawn-helper를 0755가 아니라 0644로 풀어버리는 버그였다. Windows/Linux에서는 증상이 안 나타났는데, 실행 경로가 다르거나 npm이 파일을 다른 방식으로 설치해주는 차이 때문으로 보인다. macOS arm64에서만 드러난 셈이다. chmod +x를 적용하고 다시 열자 세션이 정상적으로 살아났다.

바뀐 것:

항목 수정 전 수정 후
spawn-helper 권한 -rw-r--r-- (0644) -rwxr-xr-x (0755)
TMPDIR 링크 경로 그대로 사용 canonical 경로(/private/var/...) 사용
로컬 세션 실행 `posix