이번 주에는 Mac 노드를 먼저 늘리지 말고, runs-on 라우팅, Runner Group 권한, 노드 점유, macOS 서비스 순서로 원인을 분리해야 합니다. GitHub Actions Mac Runner 계속 대기 중인 문제는 대개 “조건에 맞는 Runner가 없음”, “조건에 맞는 Runner가 모두 사용 중임”, “온라인으로 보이지만 작업을 받지 못함” 가운데 하나입니다. 원인을 확인한 뒤 라우팅 수정, 서비스 복구, 노드 재등록, 용량 확장 중 하나를 선택합니다.

이 글은 GitHub Actions 자체 운영 Mac으로 Xcode 빌드를 실행하다가 작업이 계속 대기하는 모바일 개발자를 위한 내용입니다. Runner 태그와 Runner Group, 저장소 접근 범위, 상시 실행 서비스를 관리하는 DevOps 엔지니어와 기존 원격 Mac을 고칠지 다시 등록할지 판단해야 하는 플랫폼 담당자에게도 적합합니다.

01

대기 상태를 먼저 네 가지로 나눕니다

관리 화면에서 Idle이라고 표시되는데 Job이 queued로 남으면, 곧바로 Mac 고장이나 노드 부족으로 판단하면 안 됩니다. 작업 기록에서 먼저 다음 상태를 구분해야 합니다.

  • 앞선 Job이나 조건이 끝나기를 기다리는 상태
  • 승인이나 환경 보호 규칙을 기다리는 상태
  • 동시 실행 제한으로 대기하는 상태
  • 자체 운영 Runner를 찾지 못해 대기하는 상태

GitHub Actions의 동시 실행 제한은 공식 동시 실행 설정 문서에서 확인할 수 있습니다. 이 제한에 걸린 작업은 Mac Runner의 태그를 고쳐도 바로 실행되지 않습니다.

먼저 워크플로 실행 기록에서 Job의 대기 문구와 runs-on 값을 저장합니다. 이어서 Runner 관리 화면에서 대상 Runner의 레이블, 소속 그룹, 온라인 또는 유휴 상태를 기록합니다. 이때 YAML, 레이블, 그룹 정책을 동시에 수정하지 말아야 합니다. 증거를 남기기 전에 여러 항목을 바꾸면 어떤 변경이 문제를 해결했는지 확인할 수 없습니다.

02

라우팅 조건과 Runner Group을 분리해 확인합니다

모든 runs-on 조건이 실제 레이블과 맞는지 봅니다

runs-on에 여러 레이블이 들어 있으면 하나가 아니라 모든 조건을 충족하는 Runner가 선택됩니다. GitHub의 자체 운영 Runner 레이블 안내는 기본 레이블과 사용자 지정 레이블을 구분해 설명합니다.

예를 들어 다음 작업은 세 조건을 동시에 요구합니다.

jobs:
  diagnose:
    runs-on: [self-hosted, macos, arm64, xcode-ci]
    steps:
      - run: |
          uname -m
          sw_vers
          echo "runner=$RUNNER_NAME"

노드에 self-hosted, macos, arm64만 있고 xcode-ci가 없다면 관리 화면에서 Idle로 보여도 이 작업의 후보가 아닙니다. 반대로 노드 재구성 뒤 사용자 지정 레이블만 빠져도 같은 현상이 생깁니다. 레이블의 대소문자, 하이픈, 철자를 YAML과 관리 화면에서 그대로 대조해야 합니다.

진단용 작업은 운영 빌드와 분리해야 합니다. 생산 작업의 runs-on을 self-hosted처럼 넓은 조건으로 바꾸면 잘못된 노드에서 서명이나 배포가 실행될 수 있습니다. 최소 명령만 수행하는 작업으로 라우팅을 확인한 뒤 원래 레이블을 유지해야 합니다.

GitHub의 작업에 Runner를 선택하는 공식 설명은 runs-on 조건과 Runner 선택 관계를 다룹니다. 이 문서와 자체 운영 Runner 라우팅 참고 문서를 함께 보면서 관리 화면의 실제 레이블을 확인하는 편이 안전합니다.

레이블 일치와 저장소 권한은 별개입니다

레이블이 모두 맞아도 Runner Group이 대상 저장소에 허용되지 않으면 작업은 해당 노드로 가지 않습니다. 조직 수준에서 등록한 Runner일수록 그룹의 저장소 접근 범위를 별도로 확인해야 합니다.

확인 순서는 다음과 같습니다.

  1. Runner가 어느 조직 또는 저장소 수준에 등록되어 있는지 기록합니다.
  2. 해당 Runner가 속한 Runner Group을 확인합니다.
  3. 그룹의 저장소 접근 정책에서 대상 저장소가 허용되는지 확인합니다.
  4. 민감한 단계가 없는 임시 워크플로로 그룹 라우팅을 시험합니다.
  5. 정책 수정 전후에 작업에서 사용할 수 있는 Runner 범위를 기록합니다.

그룹 권한 변경은 다른 저장소가 예상하지 못한 Runner를 사용하게 만들 수 있습니다. 반대로 범위를 너무 좁히면 정상 레이블을 가진 노드도 보이지 않습니다. Runner Group 접근 관리 문서를 기준으로 저장소 단위 허용 범위를 확인하고, 검증이 끝나면 임시 정책을 되돌립니다.

03

노드 점유와 macOS 서비스 장애를 구별합니다

조건을 만족하는 노드가 실제로 바쁜지 확인합니다

라우팅과 그룹 권한이 맞다면 대상 Runner가 실제로 작업 중인지 살펴봅니다. 활동 중인 Job만 보지 말고 Mac 안의 Xcode 빌드, Simulator 테스트, 서명 또는 배포 프로세스도 확인해야 합니다. Job은 끝났지만 자식 프로세스가 남아 작업 디렉터리나 빌드 잠금을 붙잡는 경우도 있습니다.

점검 항목은 다음과 같습니다.

  • 관리 화면의 현재 Job과 워크플로 실행 기록이 서로 맞는지 확인합니다.
  • Xcode, Simulator, 테스트 프로세스가 종료되지 않았는지 확인합니다.
  • 이전 작업의 작업 공간과 캐시가 다음 작업을 막고 있지 않은지 확인합니다.
  • 정상 종료 뒤 Runner가 다시 유휴 상태로 돌아가는지 확인합니다.
  • 동일 조건의 다른 Runner도 같은 작업을 기다리는지 비교합니다.

작업이 끝났는데도 계속 바쁜 상태라면 먼저 해당 Job의 로그와 프로세스 종료 원인을 보존해야 합니다. 프로세스를 강제 종료하거나 작업 디렉터리를 지우면 복구는 빨라질 수 있지만, 다음 장애의 원인을 잃을 수 있습니다. 서명 파일이나 배포 키가 있는 노드에서는 특히 작업 공간 전체를 삭제하지 말고 담당자 승인과 복구 경로를 먼저 남겨야 합니다.

온라인 상태와 작업 수신 상태를 따로 봅니다

SSH로 Mac에 접속된다는 사실만으로 Runner가 작업을 실행할 수 있는 것은 아닙니다. 관리 화면의 상태, Runner 진단 로그, 네트워크 연결, macOS의 launchd 서비스 상태를 함께 확인해야 합니다. GitHub는 macOS 자체 운영 Runner 모니터링과 문제 해결 문서에서 이 점검 범위를 안내합니다.

서비스 계정과 작업 디렉터리 권한도 확인 대상입니다. SSH 로그인 계정과 Runner 서비스 계정이 다르면 대화형 셸에서는 성공한 명령이 서비스에서는 실패할 수 있습니다. 재부팅 뒤 서비스가 자동으로 살아났는지, 작업 디렉터리를 다시 열 수 있는지, 진단 로그에 등록 상태와 연결 오류가 어떻게 남았는지 확인합니다.

필요한 경우 다음처럼 현재 환경의 핵심 정보만 수집합니다.

whoami
pwd
uname -m
sw_vers
launchctl list | grep -i runner

출력 예시는 환경에 따라 달라지므로 특정 숫자나 상태 문자열을 성공 기준으로 고정하면 안 됩니다. 중요한 것은 서비스가 실행 중인지, 올바른 계정과 경로를 사용하는지, 재시작 뒤에도 같은 상태가 유지되는지입니다.

서비스 재설치나 Runner 재등록은 마지막 복구 수단으로 둡니다. 재등록 전에 기존 로그와 설정 위치를 보존하고, 새 등록에 사용할 권한과 복구 토큰을 준비해야 합니다. Runner 삭제나 토큰 폐기는 기존 노드가 더 이상 작업을 받지 못하게 만들 수 있으므로, 공식 Runner 제거 절차를 확인한 뒤 실행해야 합니다.

04

복구 판단을 위한 최소 재현과 재검증

다음 순서로 작업을 실행하면 라우팅, 노드, 용량 문제를 분리할 수 있습니다.

  1. 상태를 고정합니다. Job 기록, runs-on, Runner 레이블, Runner Group, 서비스 로그를 파일이나 이슈에 남깁니다.
  2. 최소 명령 작업을 실행합니다. 동일한 runs-on으로 uname, macOS 버전, Runner 이름만 출력해 라우팅을 시험합니다.
  3. 실제 도구 모음 작업을 실행합니다. Xcode 선택, 의존성 복원, 테스트 또는 빌드 단계 중 안전한 범위를 실행합니다.
  4. 생산과 가까운 작업을 실행합니다. 대상 레이블, 서명 방식, 산출물 업로드를 포함하되 배포 단계는 격리합니다.
  5. 로그와 산출물을 함께 확인합니다. 작업 시작, Runner 수신, 명령 실행, 결과 업로드가 모두 이어지는지 봅니다.
  6. 재부팅 복구를 시험합니다. 서비스가 자동으로 시작되고 같은 Runner가 다시 유휴 상태가 되는지 확인합니다.
  7. 처분을 결정합니다. 라우팅 오류면 YAML이나 그룹 정책을 고치고, 서비스 오류면 기존 노드를 복구하거나 재등록하며, 실제 점유가 지속될 때만 작업 분리나 확장을 검토합니다.

GitHub의 자체 운영 Runner 사용 문서는 워크플로에서 자체 운영 Runner를 지정하는 기본 조건을 설명합니다. 이 조건을 만족하는 최소 작업조차 실행되지 않으면 Xcode 빌드 성능이나 노드 수를 논의하기 전에 라우팅과 서비스부터 다시 봐야 합니다.

05

자주 확인하는 대기 원인

GitHub Actions 자체 운영 Runner가 온라인인데 작업을 받지 않는 경우

온라인은 연결 상태의 일부일 뿐입니다. 작업의 모든 레이블과 그룹 접근 권한이 맞는지 확인한 뒤, 진단 작업으로 실제 수신 여부를 확인해야 합니다. 온라인과 유휴 상태가 모두 정상이어도 저장소가 그룹 사용 대상이 아니면 작업은 대기할 수 있습니다.

runs-on이 맞는데 Job이 계속 대기하는 경우

YAML의 레이블 목록과 관리 화면의 실제 레이블을 한 글자씩 비교합니다. 기본 레이블만 확인하지 말고 아키텍처와 도구 모음용 사용자 레이블까지 대조해야 합니다. 넓은 레이블로 우회하는 대신 최소 진단 작업을 같은 조건으로 실행해야 합니다.

Mac Runner가 Idle인데 워크플로가 실행되지 않는 경우

Runner Group 정책, 저장소 허용 범위, 동시 실행 제한을 함께 확인합니다. Idle은 해당 작업을 실행할 권한이나 조건이 있다는 표시가 아닙니다. 작업 기록에 표시된 대기 사유가 Runner 검색 실패인지, 앞선 실행이나 승인 대기인지 먼저 구분합니다.

Runner Group을 지정한 저장소에서 사용할 수 없는 경우

그룹의 허용 대상에 저장소가 포함되어 있는지 확인합니다. 조직 전체에 Runner를 등록했다는 사실만으로 모든 저장소가 사용할 수 있는 것은 아닙니다. 임시 검증 작업으로 정책을 확인한 뒤, 필요 이상으로 그룹 범위를 넓히지 않습니다.

원격 Mac Runner를 추가할 시점

태그와 그룹 권한이 맞고 서비스도 정상이며, 조건을 만족하는 모든 노드가 실제 작업 중인데 큐가 반복해서 쌓일 때입니다. 그 전에는 노드를 추가하기보다 작업을 빌드, 테스트, 배포 풀로 나누거나 비정상 점유를 제거하는 편이 정확합니다.

06

수정, 재등록, 확장을 결정하는 표

확인 결과 주된 원인 우선 조치 다음 판단
최소 작업도 후보 Runner를 찾지 못함 레이블 또는 runs-on 불일치 레이블과 YAML 대조 실제 빌드 재검증
레이블은 맞지만 대상 저장소에 보이지 않음 Runner Group 접근 정책 저장소 허용 범위 수정 임시 작업으로 그룹 재검증
조건을 만족하는 노드가 모두 작업 중 실제 용량 또는 작업 점유 활동 Job과 잔류 프로세스 확인 지속되면 작업 풀 분리 또는 확장
관리 화면은 온라인이나 작업을 받지 못함 서비스 계정, 로그, 네트워크, launchd 문제 서비스와 로그 복구 재부팅 뒤 자동 복귀 확인
등록 상태가 손상되었고 복구가 안 됨 Runner 등록 정보 문제 로그 보존 후 재등록 기존 노드 폐기 여부 결정
최소 작업과 실제 Xcode 작업이 모두 성공 일시적인 대기 또는 선행 조건 워크플로 조건 확인 반복 큐일 때만 용량 검토

현재 방식이 사내 Mac 한 대나 불안정한 개인 개발 장비에 의존한다면, 작업 중단 시 수동 로그인과 재시작이 필요하고 서비스 계정과 네트워크 상태를 담당자가 직접 관리해야 하며, 예비 빌드 노드를 즉시 확보하기도 어렵습니다. 반대로 NodeMini의 원격 Mac은 격리된 Mac을 별도 CI 검증 노드로 사용하려는 경우에 적합합니다. 먼저 원격 Mac 개발 환경을 확인하고, 실제 운영 전에는 Mac mini 렌탈 선택지를 기준으로 필요한 기간과 접속 방식을 비교하는 편이 안전합니다.

기존 Runner가 안정적으로 작업을 받지 못하거나 장애 중에도 Xcode 빌드를 이어가야 한다면, 한 대를 바로 추가하기보다 격리된 원격 Mac에서 같은 runs-on, 그룹 정책, 서비스 복구 절차를 먼저 재현해야 합니다. 그 검증이 통과한 뒤에야 NodeMini의 원격 Mac을 보조 빌드 노드로 쓰는 선택이 운영상 의미를 가집니다. 반대로 장기간 고정된 고부하 작업이나 물리 장비 연결이 필요한 경우에는 직접 보유한 Mac이 더 적합할 수 있습니다.