클라우드 Mac에서 리눅스 컨테이너를 돌려 iOS와 백엔드 하이브리드 CI 연결하기

CI/CD ·약 9분 읽기

클라우드 Mac에서 리눅스 컨테이너를 돌려 iOS와 백엔드 하이브리드 CI 연결하기

당신의 저장소에는 iOS 앱과 그 백엔드 서비스가 함께 들어 있다——백엔드는 docker-compose로 데이터베이스, 메시지 큐, 몇 개의 마이크로서비스를 띄우며, 통합 테스트는 실제로 이 컨테이너들에 연결되어야만 돌아간다. iOS 부분은 HireVPS의 클라우드 Mac mini를 빌려 Xcode 빌드를 하고 있고, 여기까지는 모든 게 순조로웠다. 그런데 CI가 같은 머신에서 백엔드 통합 테스트까지 함께 돌리도록 만들려는 순간, Apple Silicon에는 네이티브 Linux 커널이 없어서 docker run이 곧바로 데몬을 찾을 수 없다는 오류를 낸다는 사실을 깨닫게 된다. 이건 설정 문제가 아니라 아키텍처 문제다——Docker는 macOS에서는 처음부터 "빌려 쓰는" 방식으로 동작해 왔다.

시나리오: 클라우드 Mac에서도 리눅스 컨테이너를 돌려야 하는 이유

monorepo는 점점 흔해지고 있고, 하나의 PR이 iOS 클라이언트와 백엔드 API를 동시에 수정하는 경우도 많다. iOS 쪽만 테스트해서는 프로토콜 불일치 문제를 전혀 발견할 수 없다. 이상적인 파이프라인은 다음과 같다: 같은 러너에서 먼저 Xcode로 빌드하고 유닛 테스트를 실행한 뒤, docker-compose로 정의한 백엔드 의존성을 띄우고 한 차례 엔드투엔드 통합 테스트를 돌리고, 마지막에 결과를 종합해서 보고하는 것이다. 이렇게 하면 얻는 이점은 명확하다——CI 환경을 두 세트로 유지할 필요가 없고, 머신 간 통신을 위해 네트워크 정책에 구멍을 낼 필요도 없다. 전제 조건은 이 클라우드 Mac이 리눅스 컨테이너를 돌릴 수 있어야 한다는 것이다.

Apple Silicon에는 네이티브 리눅스 커널이 없기 때문에, "Docker를 돌린다"는 어떤 방식이든 본질적으로는 먼저 숨겨진 리눅스 가상머신을 하나 띄우는 것이다——성능이 좋은지 나쁜지는 거의 전적으로 이 VM에 얼마나 많은 CPU와 메모리를 할당하느냐에 달려 있다.

준비 작업: 가벼운 가상화 방식 선택하기

macOS에서 컨테이너를 돌리는 주요 방법은 두 가지다——Docker Desktop과 Colima(네이티브 docker CLI와 함께 사용). 둘 다 기본적으로 Apple의 Virtualization.framework를 이용해 경량 리눅스 VM을 띄운다는 점은 같지만, 형태와 적합한 시나리오가 다르다.

Docker Desktop과 Colima의 선택 기준

항목 Docker Desktop Colima
사용 방식 GUI + 백그라운드 데몬 순수 CLI
실행 방식 수동 또는 로그인 시 자동 실행 스크립트에서 한 줄 명령으로 실행
리소스 사용량 비교적 높음, 여러 프로세스 상주 가벼움, 필요할 때만 시작/종료
적합한 시나리오 로컬에서의 일상적인 디버깅 무인 운영되는 CI 러너
라이선스 제한 기업 규모에서는 유료 라이선스 필요 오픈소스, 무료

무인으로 운영되는 러너에서 도는 CI에는 Colima가 확실히 더 적합하다. GUI 세션에 의존하지 않고, 셸 스크립트 안에서 한 줄 명령으로 띄우고 끝나면 곧바로 종료할 수 있어 고아 프로세스가 메모리를 계속 차지하는 일이 없다.

설치와 리소스 할당

클라우드 Mac mini에서 먼저 Homebrew로 툴체인을 설치한다:

brew install colima docker docker-compose docker-buildx

colima start \
  --cpu 4 \
  --memory 12 \
  --disk 60 \
  --vm-type=vz \
  --mount-type=virtiofs

docker context use colima
docker compose -f docker-compose.ci.yml up -d --wait

--vm-type=vz는 Apple 네이티브 가상화 백엔드를 사용한다(초기 QEMU 모드보다 훨씬 빠르다). --mount-type=virtiofs는 컨테이너가 마운트하는 프로젝트 디렉터리의 읽기/쓰기 성능을 로컬 디스크에 가깝게 만들어준다. 이 두 파라미터를 붙이지 않으면 빌드 속도와 파일 I/O가 눈에 띄게 떨어진다.

리소스 할당에 만능 공식은 없지만, 경험적으로 시작할 만한 기준은 있다: Colima의 VM에는 호스트 메모리의 50%~70%를 남겨두고, CPU 코어는 대략 절반 정도를 Xcode 빌드용으로 남긴다. 탑재된 메모리 용량에 대응시키면 대략 다음과 같이 시작할 수 있다(구체적인 사양은 콘솔에서 현재 선택 가능한 옵션을 확인할 것):

기기 메모리 Colima 권장 메모리 Colima 권장 CPU
16GB 6GB 2코어
32GB 12GB 4코어
48GB 20GB 6코어
64GB 28GB 8코어

Xcode 빌드와 Colima가 동시에 도는 경우, 메모리 할당을 너무 높게 잡으면 양쪽이 서로 리소스를 빼앗아 swap이 발생하면서 빌드 시간이 오히려 늘어난다——이 균형점은 정식으로 CI에 접목하기 전에 전체 파이프라인을 몇 차례 돌려보며 조율할 가치가 있다.

CI에 연결하기: self-hosted 러너가 리눅스 컨테이너를 인식하도록 하기

러너가 GitHub Actions의 self-hosted 타입이라면, job에 Colima를 시작하고 테스트를 실행한 뒤 정리하는 단계를 추가하면 되고, 별도의 서비스 컨테이너 선언은 필요 없다:

jobs:
  hybrid-ci:
    runs-on: [self-hosted, macos, cloud-mac]
    steps:
      - uses: actions/checkout@v4
      - name: Xcode build & unit test
        run: |
          xcodebuild -scheme App -destination "platform=iOS Simulator,name=iPhone 15" test
      - name: Bring up backend containers
        run: |
          colima start --cpu 4 --memory 12 --vm-type=vz --mount-type=virtiofs
          docker compose -f docker-compose.ci.yml up -d --wait
      - name: Integration tests
        run: ./scripts/run-integration-tests.sh
      - name: Teardown
        if: always()
        run: |
          docker compose -f docker-compose.ci.yml down -v
          colima stop

if: always() 단계가 핵심이다: 테스트가 실패하더라도 컨테이너와 VM은 반드시 종료해야 한다. 그렇지 않으면 장기 임대한 클라우드 Mac에 고아 VM이 계속 쌓이면서 메모리를 차지해 다음 빌드를 느리게 만든다.

캐시 전략: 이미지 레이어와 의존성 재사용

Colima VM이 재시작될 때마다 이미지를 다시 받고 의존성을 다시 설치한다면 CI 소요 시간이 계속 길어진다. 간단하면서 효과적인 방법 두 가지가 있다:

  1. 이미지 레이어를 디스크에 유지하기: 매번 colima delete를 하지 말고 colima stop/colima start만 사용한다. VM 디스크(기본적으로 ~/.colima)에는 이미 받은 이미지 레이어가 남아 있어 재시작 후 다시 다운로드할 필요가 없다.
  2. 빌드 캐시용 볼륨 마운트하기: 백엔드 Dockerfile에서 node_modules, vendor, .cargo 같은 의존성 디렉터리에 이름이 지정된 volume을 선언하고, docker compose--wait과 함께 사용한다. 첫 빌드는 조금 느려지겠지만, 이후 증분 빌드에서는 시간을 크게 절약할 수 있다.

앞서 언급한 virtiofs 마운트와 함께 사용하면 프로젝트 디렉터리의 읽기/쓰기는 거의 병목이 되지 않는다. 정말 눈여겨봐야 할 부분은 네트워크 계층이다——통합 테스트가 외부 API에 접근해야 한다면, 테스트 환경 전용 mock이나 샌드박스 주소를 따로 설정해서 CI가 모르는 사이에 프로덕션 엔드포인트를 호출하지 않도록 해야 한다.

흔한 함정과 체크리스트

실제로 도입하는 과정에서 자주 걸려드는 함정들을 우선순위대로 정리했다:

이 흐름을 한 번 잘 정리해두면, 같은 클라우드 Mac mini가 iOS 빌드 머신과 백엔드 통합 테스트 환경을 동시에 맡을 수 있다. 머신 간 네트워크와 인증 정보를 조율할 필요도 없어지고, PR을 제출하면 하나의 파이프라인이 완전한 성공/실패 신호를 바로 알려준다.

자주 묻는 질문

Apple Silicon 클라우드 Mac에서 Docker를 네이티브로 실행할 수 있나요?

불가능합니다. Docker Desktop과 Colima 모두 Virtualization.framework로 숨겨진 리눅스 가상머신을 띄우고 컨테이너는 그 안에서 실행되므로, 성능은 할당한 CPU와 메모리에 달려 있습니다.

CI에는 Colima와 Docker Desktop 중 무엇이 좋나요?

CI에는 Colima를 권장합니다. CLI 도구라 리소스 사용량이 적고 시작이 빨라 무인 러너에서 스크립트로 자동 기동하기 좋습니다. Docker Desktop은 로컬 GUI 디버깅에 더 적합합니다.

메모리 용량별로 Colima 리소스는 어떻게 배분해야 하나요?

일반적으로 호스트 메모리의 50%~70%를 Colima VM에 배정합니다. 예를 들어 32GB 호스트라면 12GB, 4코어가 기준이 됩니다. 정확한 구성은 콘솔에서 현재 선택 가능한 옵션을 확인한 뒤 부하 테스트로 조정하세요.

HireVPS Mac

지금 전용 클라우드 Mac mini를 이용해 보세요

일 단위 대여로 시작하고, 2분 안에 SSH/VNC 접속 정보를 받아 언제든지 사양을 업그레이드할 수 있습니다.

Mac mini 바로 대여하기