증상

git push origin master를 실행하면 아무 반응 없이 터미널이 멈춘다. 수십 초가 지나도 진행이 없다. Ctrl+C로 강제 종료하고 다시 시도해도 같은 현상이 반복된다.

에러 메시지는 없다. 커서가 깜빡이는 상태로 그냥 멈춰 있다. git push --verbose를 붙여도 자격증명 요청 단계에서 진행이 멈춘다.

$ git push origin master

이 상태에서 1분이 지나면 타임아웃과 함께 아래와 같은 메시지가 뜰 수 있다.

fatal: unable to access 'https://github.com/...': The requested URL returned error: 403

또는 아예 타임아웃 없이 무한정 대기하기도 한다. 재현이 불규칙하다. 몇 번은 정상 동작하다가 갑자기 멈추는 경우도 있어 처음에는 네트워크 문제로 오해하기 쉽다.


진단

hang이 osxkeychain 문제인지 확인하는 방법은 두 가지다.

방법 1 — GIT_TRACE로 어디서 멈추는지 확인

GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push origin master 2>&1

출력에서 helper: osxkeychain get 직후에 로그가 멈추면 osxkeychain 헬퍼 호출에서 블로킹된 것이다.

20:15:33.401234 credential.c:62     git credential fill
20:15:33.401891 run-command.c:643   starting command: git credential-osxkeychain get
# ← 이 다음 줄이 나오지 않고 hang

방법 2 — 헬퍼를 직접 호출해 보기

echo "protocol=https
host=github.com" | git credential-osxkeychain get

이 명령을 실행했을 때 응답이 없으면 osxkeychain 헬퍼 자체가 블로킹 중인 것이다. 정상 동작한다면 아래처럼 즉시 자격증명을 반환한다.

protocol=https
host=github.com
username=<your-username>
password=ghp_xxxx...

한 가지 추가 확인: git config --global --list | grep credential을 실행해서 credential.helper가 중복으로 등록되어 있는지 확인한다. 여러 줄이 출력된다면 헬퍼 체인이 꼬인 것일 수 있다.

$ git config --global --list | grep credential
credential.helper=osxkeychain
credential.helper=/usr/local/share/gcm-core/git-credential-manager  # GCM이 추가로 설치된 경우

이 경우 중복을 정리하거나 우선순위가 명확한 단일 헬퍼로 교체해야 한다.


원인

macOS는 Git 자격증명(GitHub 토큰, 비밀번호 등)을 Keychain에 저장하고, osxkeychain 헬퍼를 통해 꺼내 쓴다. Git 전역 설정을 확인하면 아래와 같이 설정되어 있다.

$ git config --global credential.helper
osxkeychain

osxkeychain 헬퍼는 macOS Keychain 서비스와 통신한다. 정상 상태에서는 Keychain에서 자격증명을 즉시 가져와 Git에 넘겨준다. 하지만 몇 가지 상황에서 이 통신이 응답을 받지 못하고 무기한 대기 상태에 빠진다.

흔히 발생하는 상황은 다음과 같다.

macOS 업데이트 직후: 시스템 업그레이드 후 Keychain 데이터베이스가 잠기거나, com.apple.securityd 데몬이 재시작하면서 일시적으로 Keychain 접근이 불가능한 상태가 된다.

세션 전환 또는 절전 복귀: 화면 잠금 해제 직후 또는 절전 모드에서 복귀한 직후, Keychain 서비스가 아직 완전히 준비되지 않은 상태에서 Git이 자격증명 요청을 보내면 응답이 오지 않는다.

비밀번호 정책 변경: 회사 정책으로 인해 macOS 계정 비밀번호가 변경됐을 때, Keychain이 기존 비밀번호로 잠겨 있으면 자격증명 조회가 차단된다.

Git Credential Manager 충돌: Homebrew나 다른 경로로 설치한 도구들이 credential.helper를 중복으로 등록한 경우, 헬퍼 호출 체인이 꼬이면서 응답 없는 대기 상태가 된다.

공통점은 osxkeychain 헬퍼가 macOS 시스템 서비스에 강하게 의존한다는 것이다. 해당 서비스가 조금이라도 불안정한 순간, Git push가 조용히 멈춘다.


해결

gh CLI(GitHub CLI)가 제공하는 git-credential 헬퍼로 교체한다.

전제 조건

gh CLI가 설치되어 있고 GitHub 계정으로 인증이 완료된 상태여야 한다.

# 설치 확인
$ gh --version
gh version 2.x.x (...)

# 인증 상태 확인
$ gh auth status
github.com
  ✓ Logged in to github.com as <username> (...)
  ✓ Git operations for github.com configured to use https protocol.

gh auth login으로 인증하지 않은 경우 먼저 인증을 완료해야 한다.

설정 변경

git config --global credential.helper '!gh auth git-credential'

변경 후 확인:

$ git config --global credential.helper
!gh auth git-credential

이제 git push를 실행하면 osxkeychain 대신 gh auth git-credential이 호출된다.

동작 확인

$ git push origin master
Enumerating objects: ...
Counting objects: ...
Writing objects: 100% ...

이전과 달리 자격증명 요청 단계에서 멈추지 않고 바로 진행된다.


왜 이 방법인가

gh auth git-credential은 GitHub CLI가 관리하는 인증 상태를 사용한다. 핵심은 Git이 더 이상 git credential-osxkeychain get을 직접 호출하지 않는다는 점이다.

gh auth login 과정에서 획득한 OAuth 토큰은 기본적으로 시스템 credential store에 안전하게 저장된다. credential store를 사용할 수 없거나 문제가 있으면 gh는 파일 저장으로 fallback한다. 어느 쪽이든 Git 입장에서는 osxkeychain 헬퍼 대신 gh auth git-credential만 호출하면 된다. 그래서 Git의 자격증명 헬퍼 체인에서 발생하던 osxkeychain 블로킹을 우회할 수 있다.

[git push] → [credential.helper 호출]
                    ↓
  [구버전] osxkeychain → macOS Keychain → securityd (여기서 hang)
  [신버전] gh auth git-credential → gh 인증 저장소에서 토큰 반환

보안 측면에서도 흐름이 명확하다. GitHub Personal Access Token을 Git 설정에 직접 넣지 않고, gh auth refreshgh auth logout으로 토큰을 명시적으로 관리할 수 있다. 현재 토큰이 어디에 저장되어 있는지는 gh auth status에서 확인할 수 있다.

추가로, 이 설정은 github.com에 대한 자격증명 요청에만 gh auth git-credential이 응답한다. 다른 Git 호스트(GitLab, Bitbucket 등)는 별도의 헬퍼를 그대로 사용한다.


특정 저장소에만 적용하기

전역 설정을 바꾸고 싶지 않다면 저장소별로 적용할 수 있다.

# 현재 저장소에만 적용
git config credential.helper '!gh auth git-credential'

--global 없이 실행하면 현재 저장소의 .git/config에만 기록된다.


기존 osxkeychain 항목 정리 (선택)

Keychain에 남아 있는 오래된 GitHub 자격증명이 충돌을 일으킬 가능성을 완전히 없애려면 정리하는 것이 좋다.

방법 1 — Keychain 접근 앱 사용

  1. Keychain Access.app을 연다 (Spotlight: Keychain Access 검색).
  2. 검색창에 github.com 입력.
  3. 목록에 표시된 Internet Password 항목을 삭제.

방법 2 — 명령줄

git credential-osxkeychain erase <<EOF
protocol=https
host=github.com
EOF

이 명령은 osxkeychain에 저장된 github.com HTTPS 자격증명 항목을 삭제한다.


원복 방법

osxkeychain으로 되돌리려면:

git config --global credential.helper osxkeychain

정리

항목기존 (osxkeychain)변경 후 (gh auth git-credential)
자격증명 저장 위치macOS Keychaingh 인증 저장소
Git이 호출하는 헬퍼git credential-osxkeychaingh auth git-credential
hang 재현 가능성있음 (Git의 Keychain 헬퍼 상태 의존)낮음 (osxkeychain 헬퍼 직접 호출 우회)
적용 범위모든 Git 호스트GitHub 요청만
추가 설치 필요없음gh CLI 필요

macOS Keychain과 Git 자격증명 통합은 평소에는 투명하게 동작한다. 하지만 시스템 업데이트, 세션 전환, 비밀번호 정책 변경 같은 특정 상황에서 조용히 hang이 발생한다. 에러 메시지가 없기 때문에 처음에는 네트워크 문제나 서버 오류로 오해하기 쉽다.

gh CLI 인증 헬퍼는 macOS 시스템 서비스를 우회하는 가장 단순한 해결책이다. GitHub를 사용하는 macOS 개발 환경이라면, gh auth login을 한 번 해뒀을 때 credential.helper도 같이 설정해 두는 것을 권장한다.