← 개발 일기로

Mac M4 CI는 언제 분리해야 할까? 단일 호스트에서 듀얼 노드로의 결정 모델과 마이그레이션 (2026)

OpenClaw · 2026.06.23 · 약 11분

Mac M4 CI 빌드 노드와 OpenClaw Gateway 듀얼 노드 아키텍처

6월 초 Xcode CI와 OpenClaw Gateway를 같은 캐나다 M4 한 대에 넣고, launchd Nice=-5와 병렬 컴파일 제한으로 2주를 버텼다. 3주째부터 업무 팀이 IM에서 「Gateway 또 느려요」라고 불평하기 시작했다——빌드 로그는 정상인데 curl 헬스체크만 피크 시간에 50ms에서 400ms 이상으로 튄다. 동시성을 낮추고 DerivedData를 비우고, 잠시 24GB 플랜으로 올려도 문제는 「하루 두 번」에서 「하루 한 번」으로만 줄었다.

설정 오류가 아니라 단일 호스트 리소스 모델이 한계에 닿았다는 신호다. 포트는 충돌하지 않는다(20300 vs 18789), CPU 코어도 충분하다. 실제로 싸우는 건 통합 메모리와 swap이다. 본문은 동일 호스트 배치와 launchd 튜닝 다음 단계——언제 듀얼 노드로 나눌지, 토폴로지 그리기, Channels를 깨뜨리지 않고 전환하는 방법. 공식 메모리·프로세스 동작은 Apple Xcode 빌드 캐시 문서, Tailscale 구성은 Tailscale 설치 가이드 참고.

결론부터:분수령은 리소스 격리이지, 「한 대 더 사기」가 아니다.

  • 네 가지 하드 시그널, 하나만 해당해도 분리

    빌드 ≥50회/일, 동시 ≥3본, Gateway가 최종 사용자 대상, 또는 주간 swap Critical ≥3회——같은 호스트에서 Nice만 조정하는 건 미루기일 뿐.

    ≥50회/일

  • 최소 듀얼 노드:빌드 머신 + Gateway 전용

    빌드 노드는 24GB+와 대용량 SSD; Gateway 노드는 16GB로 상주 ~500MB 충분. M4 두 대를 Tailscale 내부망으로 연결, 공인망은 필요한 입구만 노출.

    16GB Gateway 전용

  • 마이그레이션 핵심:상태와 DNS, 재설치가 아님

    설정 디렉터리 rsync, token 재사용, Tailscale MagicDNS로 트래픽 전환. 빌드 머신은 무중단, Gateway 블루/그린 창 15분 이내.

    블루/그린 ≤15분

1. 왜 동일 호스트 구성이 「갑자기 부족해지는」가

많은 팀의 첫 클라우드 Mac은 세 가지 역할:xcodebuild, OpenClaw Gateway 18789, 가끔 VNC로 키체인 클릭. 초기 부하는 낮아 16GB가 넉넉해 보인다. 브랜치 증가, UI 테스트 병렬, Channels가 내부 시험에서 대외 서비스로——메모리 곡선이 「톱니」에서 「평지」로. 빌드 종료 후 10분에도 compressed 페이지가 8GB 이상, Gateway heap이 swap으로 밀린다.

동일 호스트 튜닝(동시성 감소, Nice 상향, 캐시 정리)은 피크 겹침 확률을 낮출 뿐, 피크 자체는 없애지 못한다. 시간축에서 두 피크가 거의 필연적으로 겹치면——예: APAC 낮 빌드, 북미 저녁 IM 피크——파라미터 최적화가 아니라 스케줄러에 내기하는 것이다. Apple Silicon 통합 메모리에는 독립 VRAM 버퍼가 없고, Xcode와 Node.js Gateway는 같은 물리 풀을 다툰다. memory_pressure가 Warn에 들어가면 사용자에게는 지연 지터가 체감되고, CI에는 간헐적 타임아웃과 서명 단계 실패가 난다.

분리의 본질은 「스케일 신화」가 아니라 압축 불가능한 피크를 나누는 것:빌드 피크는 빌드 노드에만, Gateway 상주 메모리는 xcsbuildd에 영원히 빼앗기지 않게. GitHub Actions 셀프호스트 macOS Runner를 클라우드 Mac에 올리기에서 「전용 Runner에 데스크톱을 섞지 않는다」와 같은 논리로, 여기서는 Gateway와 CI를 나눈다.

2. 세 가지 토폴로지 분류:동일 호스트, 듀얼 노드, 트리플 노드

먼저 분류 후 선정——바로 「두 대 추가」는 피한다:

  • T0 동일 호스트 공존:M4 한 대에 Xcode Server / 셀프호스트 Runner + Gateway. 일일 빌드 <30, Gateway 내부만, 간헐 지연 허용.
  • T1 듀얼 노드(본문 주인공):노드 A는 CI 전담(24GB+, 대 SSD); 노드 B는 Gateway 전담(16GB면 충분). Tailscale 또는 DC 내부망, Channels·Dashboard는 B, 빌드 트리거는 A.
  • T2 트리플 노드:T1에 「서명/업로드 전용」또는 「병렬 테스트 전용」추가. 일일 빌드 >150, TestFlight 업로드와 컴파일 하드 격리 필요 시에만; 대부분 중소 팀은 T1로 충분.

비대칭 결론을 다시:문제는 M4 성능 부족이 아니라, SLA가 다른 두 서비스를 같은 메모리 풀에 묶은 것. Gateway는 99.9% 안정 응답; CI는 처리량. 동일 호스트는 하나의 SLA로 두 목표를 타협한다.

T1 듀얼 노드:빌드 머신 + Gateway 전용 노드 A · CI 빌드 머신 M4 24GB+ · 1TB SSD xcodebuild / Runner DerivedData 로컬 :20300 Xcode Server 노드 B · Gateway 전용 M4 16GB · 256GB OpenClaw Gateway Channels / Dashboard :18789 안정 저지연 Tailscale <5ms 엔지니어 SSH / CI 트리거 → A;IM / 모바일 / Agent → B
듀얼 노드 최소 모델:빌드 피크와 Gateway SLA 물리 격리

3. 동일 호스트 vs 듀얼 노드 vs 스펙 업:비교 방법

Mac M4 CI 확장 경로 비교(2026)
차원 동일 호스트 튜닝 지속 Nice / 동시성 감소 단일 32GB 업그레이드 메모리만, 토폴로지 유지 듀얼 노드로 분리 CI + Gateway 분리
근본 원인피크 겹침 완화메모리 상한 상향두 SLA 격리
Gateway 지연빌드에 따라 지터개선되나 제거 안 됨빌드 중에도 <100ms 유지 가능
월 비용(대략)최저중(업그레이드 차액)중(+16GB 소형 머신)
운영 복잡도낮음낮음중(+1대, Tailscale)
적합 단계일일 빌드 <30동시 2본, 내부 Gateway≥50회/일 또는 대외 Gateway
분리 트리거 시그널 체크리스트(하나만 해당해도 T1 권장)
시그널 임계값 관측 방법 오탐 제외
빌드 빈도≥50회/일CI 로그 / Runner 카운트수동 로컬 Archive 제외
동시 빌드 수≥3본 풀 빌드xcodebuild -jobs와 큐 깊이경량 lint는 1본으로 안 셈
Gateway 대상최종 사용자 / 7×24 Channels제품 SLA 요구순수 내부 webhook은 유예
메모리 압력주간 Critical ≥3회memory_pressure 로그일회성 누수는 먼저 조사
디스크 경합월 산출물 >50GB이고 I/O wait 높음df -h + iostatarchive 정리 후 재판단
스펙 업은 분리를 대체하지 못함
32GB 동일 호스트는 「동시 2본 + Gateway 내부 시험」에 적합. Gateway가 대외면 메모리 증설은 지터를 하루 세 번에서 한 번으로 줄일 뿐——사용자는 여전히 「또 느려」고 느낀다.

4. 시나리오별 선택:의사결정 매트릭스

  • 2인 팀, 일일 빌드 <20, Gateway 자용만:T0 유지, 동일 호스트 launchd 튜닝으로 충분.
  • APAC에서 빌드 트리거, Gateway가 IM 사용자 서비스:즉시 T1. Follow-the-sun에서 피크는 거의 필연적으로 겹치고, 동일 호스트는 짐.
  • GitHub Actions 클라우드 Runner 있고 Gateway 막 올림:Runner는 A, Gateway는 B; Runner 머신에 18789를 또 달지 말 것.
  • TestFlight 업로드와 컴파일이 디스크 다툼:먼저 T1; 그래도 부족하면 T2에 서명/upload 전용 추가. TestFlight 전문 참고, 본문과 혼동 금지.
  • 예산이 한 대뿐:Gateway SLA 우선, 빌드는 야간 배치나 동시성 감소——타협이지 장기 아키텍처가 아님.

5. 권장 조합(중첩 가능)

  1. 최소 듀얼 노드 스택:Hashvps 캐나다 M4 24GB(A, CI)+ M4 16GB(B, Gateway)+ Tailscale tailnet + openclaw doctor 주간 점검. T0에서 올리는 대다수 팀에 적합.
  2. CI 하이브리드 스택:A에 셀프호스트 Runner로 GitHub Actions; B에 Gateway + Channels. 오케스트레이션은 GitHub, 실행면은 macOS, Gateway는 빌드 피크를 안 짊어짐. 2027 macOS 빌드 시장 변화의 「환경 주권」과 같은 방향.
  3. 관측 스택:B에 Gateway 지연 프로브 상주(curl 5초 간격)+ A 빌드 종료 hook으로 memory_pressure 스냅샷; 2주 데이터로 분리 ROI를 경영층에 증명.

6. 마이그레이션 전 흔한 오해

  • 빌드 중단 후 Gateway 이전:빌드 중단 비용이 큼; Gateway는 블루/그린, 빌드는 계속.
  • 신규 머신 재설치만 하고 rsync 안 함~/.openclaw, token, Channels 페어링 상실 시 전원 재로그인.
  • 공인망에서 18789를 두 IP에 동시 노출:전환 기간은 Tailscale 또는 내부 DNS; 두 Gateway가 동시에 Channels 받지 않게.
  • 빌드 머신에서 Gateway 디렉터리 너무 일찍 삭제:롤백 창에서는 구 머신 Gateway 프로세스 유지, DNS만 전환.
  • 시계·인증서 무시:두 대 NTP 편차 >30s면 token 검증 간헐 실패; 이전일 sudo sntp -sS time.apple.com 먼저.

7. 구현 단계:7단계로 듀얼 노드 마이그레이션

아래 Runbook 전제:기존 mac-ci-01에서 CI+Gateway 공존; 신규 mac-gw-02(16GB)Gateway 전용 구매. Tailscale 설치됨(OpenClaw 일상 운영 Runbook 참고).

1단계:베이스라인 스냅샷(이전 전날)

기존 머신에서 Gateway 지연 P50/P95, 빌드 횟수, memory_pressure 분포 기록해 분리 후 비교. openclaw status와 Channels 목록 스크린샷.

bash — 베이스라인:Gateway 지연과 메모리 압력
# 延迟采样 60 次
for i in $(seq 1 60); do
  curl -o /dev/null -s -w "%{time_total}\n" http://127.0.0.1:18789/health
  sleep 5
done | sort -n | awk '{a[NR]=$1} END{print "p50="a[int(NR*0.5)],"p95="a[int(NR*0.95)]}'

memory_pressure
vm_stat | head -8

2단계:신규 머신 초기화와 Tailscale 가입

mac-gw-02에서 macOS 업데이트, Homebrew, Node, Tailscale; mac-ci-01과 상호 ping <5ms 확인. 신규 머신에서 xcodebuild 실행 금지.

3단계:rsync로 Gateway 상태(유지보수 창 시작)

bash — 기존 머신에서 Gateway 전용으로 OpenClaw 설정 동기화
# 在原机 mac-ci-01 执行;先停 Gateway 避免写入分裂
sudo launchctl unload /Library/LaunchDaemons/com.openclaw.gateway.plist

rsync -avz --delete \
  ~/.openclaw/ \
  builder@mac-gw-02.tailnet-abc.ts.net:~/.openclaw/

# 同步 launchd plist
scp /Library/LaunchDaemons/com.openclaw.gateway.plist \
  builder@mac-gw-02.tailnet-abc.ts.net:/tmp/

4단계:신규 머신에서 Gateway 기동과 로컬 검수

bash — mac-gw-02에서 서비스 로드와 헬스체크
sudo cp /tmp/com.openclaw.gateway.plist /Library/LaunchDaemons/
sudo launchctl load /Library/LaunchDaemons/com.openclaw.gateway.plist

openclaw doctor
curl -s http://127.0.0.1:18789/health
sudo lsof -iTCP:18789 -sTCP:LISTEN

5단계:트래픽 전환——Tailscale MagicDNS 또는 리버스 프록시

팀이 쓰는 Gateway 호스트명(예 gateway.tailnet-abc.ts.net)을 신규 머신으로; 모바일·Channels 설정을 새 MagicDNS 이름으로. 전환 중 기존 머신에서 Gateway 재시작하지 말 것.

6단계:빌드 머신 부하 경감

Channels와 Dashboard가 신규에서 정상이면, 기존에서 Gateway launchd 언로드해 CI용 메모리 확보. 병렬 컴파일을 5–6(24GB 머신)으로 복원.

bash — 기존 빌드 머신에서 Gateway 제거, CI 동시성 복원
# mac-ci-01:确认已无流量打到 18789 后
sudo launchctl unload /Library/LaunchDaemons/com.openclaw.gateway.plist
sudo mv /Library/LaunchDaemons/com.openclaw.gateway.plist \
        /Library/LaunchDaemons/com.openclaw.gateway.plist.bak

defaults write com.apple.dt.Xcode \
  IDEBuildOperationMaxNumberOfConcurrentCompileTasks 6

7단계:48시간 관찰과 롤백 계획

기존 .openclaw 백업과 plist.bak 7일 보관. 신규 Gateway P95 >200ms 또는 Channels 끊기면 DNS를 기존으로 되돌리고 launchctl load——CI 큐는 건드리지 않음. 신규 Gateway 설치는 OpenClaw 원격 Mac 온보딩과 대조.

8. FAQ

Q1. 16GB 한 대만 있을 때, 「논리 역할」만 나눠 두 번째를 안 사도 될까?

물리 분리를 대체하지 못한다. 야간 빌드·낮 Gateway처럼 시간대를 나누는 건 가능하지만 Follow-the-sun이나 7×24 Channels에서는 다시 피크 충돌. 논리 분리의 가치는 「Gateway를 옮기면 지연이 회복되는지」 검증해 조달에 두 번째 필요성을 증명하는 것.

Q2. 듀얼 노드에 Tailscale 필수인가?

필수는 아니나 강력 권장. 같은 클라우드 내부망, WireGuard 자체 구축, SSH 터널도 가능; Tailscale 강점은 MagicDNS, ACL, 낮은 운영 부담. Hashvps 캐나다 M4 두 대가 같은 리전이면 내부 RTT 보통 <2ms, Gateway가 A의 빌드 webhook 호출에 충분.

Q3. 듀얼 노드가 단일 32GB보다 얼마나 비싼가?

플랜에 따라 다르지만 종종 「24GB 빌드 + 16GB 소형」vs「단일 32GB」에 근접. 핵심은 절대 차액이 아니라 Gateway SLA 증명 가능성——대외 서비스 팀은 다운타임으로 계산하고 월세만 보지 말 것.

Q4. GitHub Actions 호스팅 Runner 있으면 Mac 자체 구축 불필요?

환경 주권에 달림. 호스팅 macOS는 분 단위 과금으로 피크에 적합; 고정 일일 빌드 >50이고 키·DerivedData 통제하려면 클라우드 Mac 자체. Gateway는 독립 노드 권장, Runner 호스팅 여부와 무관.

Q5. 마이그레이션 실패 시 최단 롤백은?

DNS 되돌리기 + 기존에서 launchctl load. 롤백일 대규모 빌드 금지; 먼저 Gateway health와 Channel 메시지 한 건 확인 후 CI 개방. 상태 디렉터리는 새 지표 안정까지 이중 보관.

9. 요약

Mac M4 CI 분리는 실패가 아니라 동일 호스트 튜닝 성공 이후의 자연스러운 다음 단계——빌드와 Gateway를 동시에 필요함을 증명했지만, 물리적으로는 한 메모리에 더 넣으면 안 된다. 네 가지 하드 시그널, T1 듀얼 노드로 SLA 격리, 7단계 Runbook으로 블루/그린——분수령은 리소스 격리이지, 머신 대수가 아니다.

「Gateway 또 느린데 빌드는 못 멈춘다」창에 있다면 Nice를 더 조정하기보다 16GB Gateway 전용 한 대가 근본에 가깝다. 빌드는 24GB 클라우드에서 계속, Agent와 사용자는 다른 머신에서 안정된 18789——2026년 소규모 팀이 감당할 「준프로덕션」토폴로지다.

듀얼 노드 분리, 클라우드 Mac mini 두 대부터

Xcode CI와 OpenClaw Gateway를 분리하면 빌드 머신은 24GB와 대 SSD로 DerivedData를, Gateway 머신은 16GB로 7×24 저지연 상주면 된다. Hashvps 캐나다 M4 베어메탈, 전용 IPv4, SSH/VNC 즉시 사용, 같은 리전 두 대로 낮은 지연 구성——T1 듀얼 노드 출발점으로 단일 32GB 강화보다 swap 지터 격리에 유리.

동일 호스트에서 듀얼 노드로 계획 중이라면, Hashvps 클라우드 Mac mini M4는 가성비 좋은 두 번째 출발점—— 플랜 보기 , Gateway와 CI가 각자 자리를 갖도록.

Hashvps · Mac 클라우드

빌드와 Gateway, 분리하면 더 안정적

24GB CI + 16GB Gateway 전용, 베어메탈 macOS, 전용 IP, Tailscale 지원.

플랜 보기
한정 혜택