Homebrew 6.0 업데이트로 멈춰버린 Mac 온보딩 스크립트 수정하기
29 Juli 2026
0
컴퓨터/소프트웨어Related Video
5:32Homebrew 6.0 등장: Mac 소프트웨어 설치 방식의 변화
Better Stack
Comments (0)
Log in to leave a comment
No posts yet
5:32Better Stack
Log in to leave a comment
No posts yet
아침에 출근했더니 신규 입사자 온보딩 스크립트가 멈췄다는 슬랙 메시지가 수십 개 쌓여 있습니다. 터미널을 열어보니 brew install 과정에서 사용자 입력을 기다리며 한없이 멈춰 있는 상황입니다.
Homebrew 6.0으로 올라가면서 대화형 인터페이스(Ask mode)와 표준 입력(stdin) 차단 정책이 강화되었습니다. 사람이 직접 명령어를 칠 때는 문제없지만, Shell 스크립트로 백그라운드에서 돌리면 터미널이 입출력 교착 상태에 빠집니다.
팀원들의 환경 세팅 문의로 내 업무 흐름까지 깨지고 있다면 스크립트에 몇 가지 환경 변수와 예외 처리를 직접 박아 넣어야 합니다.
Homebrew 6.0은 TTY(대화형 터미널) 연결이 없는 상태에서 패키지를 깔 때 예기치 못한 입출력 대기를 일으킵니다. 터미널 대기 현상을 차단하고 완벽한 무인 실행 환경을 만들려면 스크립트 최상단에 전용 환경 변수를 명시해야 합니다.
스크립트 최상단에 다음 변수들을 추가하면 관리자 권한 요청을 제외한 모든 대화형 프롬프트와 힌트 출력이 끌립니다.
#!/usr/bin/env zsh
# Homebrew 6.0 무인 실행 환경 변수
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_ACCEPT_OUTDATED_CAVEATS=1
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
# Homebrew 경로 감지 및 로드
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -f "/usr/local/bin/brew" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
else
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
# 패키지 설치 감싸기 함수
safe_brew_install() {
local formula="$1"
if brew list "${formula}" &>/dev/null; then
echo "이미 설치됨: ${formula}"
else
if ! brew install "${formula}"; then
echo "오류 발생: ${formula} 설치 실패" >&2
return 1
fi
fi
}
safe_brew_install "git"
safe_brew_install "jq"
.zshrc 파일 대신 Homebrew 내장 설정 파일인 brew.env를 쓸 때는 export 키워드를 빼고 HOMEBREW_NO_ENV_HINTS=1 형태의 키-값 쌍으로만 적어야 문법 에러가 나지 않습니다.
6.0 버전부터 공급망 보안을 이유로 'Tap Trust Model'을 기본 적용합니다. 검증되지 않은 외부 Custom Tap이나 MD5, SHA-1을 사용하는 옛날 패키지는 로드 자체가 막힙니다.
사내 도구 배포용 Formula는 SHA-256 디지스트를 필수로 적어야 하고, brew audit --strict 검사를 통과해야 CI/CD 파이프라인이 터지지 않습니다.
# homebrew-tools/Formula/internal-api-cli.rb
class InternalApiCli < Formula
desc "사내 인프라 API 제어 및 배포 자동화 CLI 도구"
homepage "https://internal.company.net/docs/cli"
url "https://internal.company.net/downloads/cli/v2.4.0/internal-api-cli-2.4.0.tar.gz"
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
license "Proprietary"
depends_on "jq"
def install
bin.install "internal-api-cli"
end
test do
assert_match "version 2.4.0", shell_output("#{bin}/internal-api-cli --version")
end
end
사내 배포용 Formula(internal-api-cli.rb) 파일 내부에 SPDX 규격 라이선스 식별자(license "Proprietary")와 정확한 url, desc 필드를 박아놓습니다. CI/CD 파이프라인에서 파일 다운로드 후 shasum -a 256으로 값을 추출해 sed로 자동 업데이트하게 만들면 편합니다.
개발자 로컬 Mac에서는 brew trust company/tools를 한 번 실행해 사내 Tap을 신뢰 소스로 등록해두면 보안 경고 없이 바로 설치됩니다.
VS Code 터미널이나 옛날 터미널 에뮬레이터가 Intel(x86_64) 바이너리로 돌아가고 있으면, M series Mac을 쓰고 있어도 uname -m 결과가 x86_64로 나옵니다. 이상태로 Homebrew 패키지를 설치하면 /usr/local 아래에 x86 바이너리가 깔리면서 mach-o file, but is an incompatible architecture 에러를 뱉어냅니다.
터미널 환경이 Rosetta 2 아래에서 도는지 확인하고, 곧바로 arm64 네이티브로 프로세스를 다시 띄우는 조건문이 필요합니다.
#!/usr/bin/env zsh
SYSTEM_ARCH="$(uname -m)"
IS_TRANSLATED="$(sysctl -n sysctl.proc_translated 2>/dev/null || echo "0")"
if [[ "${SYSTEM_ARCH}" == "arm64" ]]; then
HOMEBREW_PREFIX="/opt/homebrew"
elif [[ "${SYSTEM_ARCH}" == "x86_64" && "${IS_TRANSLATED}" == "1" ]]; then
echo "Rosetta 2 에뮬레이션 감지. arm64 환경으로 다시 실행합니다."
exec arch -arm64 /bin/zsh "$0" "$@"
exit 0
elif [[ "${SYSTEM_ARCH}" == "x86_64" && "${IS_TRANSLATED}" == "0" ]]; then
HOMEBREW_PREFIX="/usr/local"
else
echo "지원하지 않는 아키텍처: ${SYSTEM_ARCH}" >&2
exit 1
fi
eval "$(${HOMEBREW_PREFIX}/bin/brew shellenv)"
커널 파라미터 sysctl -n sysctl.proc_translated를 조회했을 때 1이 나오면 Rosetta 2 상태입니다. 이때 exec arch -arm64 /bin/zsh "$0" "$@"를 실행하면 스크립트 전체가 arm64 쉘로 전환되면서 /opt/homebrew 경로에 올바른 바이너리가 깔립니다.
개발자마다 Homebrew 버전도 다르고 설치된 패키지도 다르면 "내 컴퓨터에서는 되는데?" 상황이 반복됩니다. declarative 방식의 Brewfile과 brew bundle check 조합을 스크립트에 넣어두면 새로 온 사람도 명령어 한 줄로 세팅을 끝냅니다.
#!/usr/bin/env zsh
set -euo pipefail
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_BUNDLE_NO_UPGRADE=1
DOTFILES_REPO="https://github.com/company/dotfiles.git"
TARGET_DIR="$HOME/.dotfiles"
if ! command -v brew &>/dev/null; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
if [[ ! -d "${TARGET_DIR}" ]]; then
git clone "${DOTFILES_REPO}" "${TARGET_DIR}"
else
git -C "${TARGET_DIR}" pull origin main
fi
BREWFILE_PATH="${TARGET_DIR}/Brewfile"
if brew bundle check --file="${BREWFILE_PATH}" &>/dev/null; then
echo "Brewfile의 모든 의존성이 최신 상태입니다."
else
brew bundle install --file="${BREWFILE_PATH}"
fi
사내 Dotfiles 저장소를 $HOME/.dotfiles에 동기화한 뒤 brew bundle check로 미설치 패키지가 있는지 먼저 확인합니다. 빠진 패키지가 있을 때만 brew bundle install을 실행하게 만들면 스크립트를 몇 번을 반복해서 실행해도 동일한 환경이 유지됩니다.