public 저장소는 URL만 있으면 누구나 clone할 수 있다. private 저장소는 다르다. GitHub에 내가 이 저장소를 볼 수 있는 사람이라는 걸 먼저 증명해야 한다.
방법을 알려주는 글은 많고, 대부분 명령어 대여섯 줄로 끝난다. 나는 그 명령어들이 각각 무엇을 만들고 어디에 등록하는지가 궁금했다. 이 글에서는 SSH 키를 만들고 GitHub에 등록해 private 저장소를 clone하기까지의 순서와 그 사이에 일어나는 인증을 정리한다.
공개키는 GitHub에, 개인키는 내 컴퓨터에
SSH 키는 공개키(public key)와 개인키(private key) 한 쌍이다. 둘은 수학적으로 연결되어 있다.
공개키는 공유해도 된다. GitHub 계정에 등록해 두면 GitHub가 이 키로 나를 확인한다.
개인키는 로컬 컴퓨터에만 두고 절대 공유하지 않는다. 내가 나라는 증거는 이 키에서 나온다.
GitHub, GitLab 같은 Git 서비스는 저장소에 접근하거나 push할 때 이 키로 인증을 요구한다. 사용자 이름과 비밀번호를 쓰는 방식보다 안전해서 널리 쓰인다.
ssh-keygen으로 키 한 쌍을 만든다
cd ~/.ssh
ssh-keygen -t rsa -C "{git 계정 이메일}" -f "{키 이름}"
명령이 끝나면 {키 이름}과 {키 이름}.pub 두 파일이 생긴다. {키 이름}이 개인키, .pub가 붙은 쪽이 공개키다.
-t rsa: 만들 키의 type을 RSA로 지정한다. RSA는 널리 쓰이는 키 유형 중 하나다.-C "{git 계정 이메일}": 키에 주석을 단다. 보통 이메일 주소를 넣어 어떤 키가 무슨 용도인지 식별한다.-f "{키 이름}": 키 파일 이름을 정한다. 기본 이름id_rsa대신 다른 이름을 쓸 수 있어서 키를 여러 개 관리할 때 편하다.-b {3072~4096}: 키 길이(bit)다. 지정하지 않으면 3072가 적용된다.
명령을 입력하면 개인키에 비밀번호(passphrase)를 걸지 묻는다.
Enter passphrase (empty for no passphrase): [여기에 비밀번호 입력]
Enter same passphrase again: [비밀번호 재입력]
비밀번호는 선택이다. 걸어 두면 개인키 파일이 유출되어도 비밀번호 없이는 쓸 수 없지만, 키를 쓸 때마다 비밀번호를 물어 온다. 엔터만 누르면 비밀번호 없는 개인키가 만들어진다. 접속이 편해지는 대신 그만큼 보안 수준은 낮아진다.
옵션 없이 ssh-keygen만 입력해도 된다. 그러면 홈 디렉토리 아래 .ssh 폴더에 RSA 키 쌍을 만들고 저장 위치와 비밀번호만 물은 뒤 나머지는 기본값으로 진행한다. 파일 이름은 id_rsa와 id_rsa.pub가 된다. 위에서 옵션을 붙인 건 키 타입, 주석, 파일 이름을 직접 정하기 위해서다.
이름을 바꾼 키는 ssh-agent에 올려야 쓰인다
ssh-agent를 실행한다.
eval "$(ssh-agent -s)"
방금 만든 개인키를 에이전트에 추가한다.
ssh-add ~/.ssh/{프라이빗키 이름}
ssh-agent는 개인키를 메모리에 들고 있다가 인증이 필요할 때 대신 처리해 주는 프로그램이다. 개인키에 비밀번호를 걸었다면 ssh-add를 실행할 때 한 번만 입력하면 되고, 이후 접속에서는 다시 묻지 않는다. 키가 여러 개여도 필요한 키를 모두 ssh-add로 올려 두면 에이전트가 맞는 키를 골라 쓴다.
-f로 이름을 바꿨다면 이 단계를 건너뛸 수 없다. ssh는 id_rsa 같은 기본 이름의 키만 알아서 찾는다. 기본 이름으로 만든 키라면 ssh-add 없이도 쓰이지만, 이름을 바꾼 키는 에이전트에 올리거나 ~/.ssh/config의 IdentityFile로 경로를 알려줘야 한다.
에이전트에 개인키가 올라갔는지는 이렇게 확인한다.
ssh-add -l
GitHub에 공개키를 등록한다
공개키 내용을 출력해서 복사한다.
cd ~/.ssh
cat {생성한 공개키 이름}.pub
복사한 내용을 **[GitHub] → [Settings] → [SSH and GPG keys]**에서 New SSH key로 붙여 넣는다.

여기까지 하면 SSH 주소로 private 저장소를 clone할 수 있다.
git clone [email protected]:{private repository 소유자 이름}/{private repository 이름}.git
clone할 때 개인키는 내 컴퓨터를 떠나지 않는다
git clone [email protected]:...을 실행하면 뒤에서 SSH 인증이 먼저 돈다.
sequenceDiagram
participant L as 로컬 (ssh + ssh-agent)
participant G as GitHub
L->>G: SSH 연결 요청
L->>G: 개인키로 만든 서명 전송
G->>G: 등록된 공개키로 서명 검증, 계정 확인
G->>G: 그 계정이 저장소에 접근 권한이 있는지 확인
G-->>L: 권한이 있으면 저장소 내용 전송개인키로 서명한다. 로컬의 ssh는 ssh-agent에 올라간 개인키(또는
~/.ssh의 기본 이름 키)로 서명을 만들어 GitHub에 보낸다. 개인키 파일 자체는 전송되지 않는다. 에이전트에 올리지 않은 키에 비밀번호가 걸려 있다면 이때 비밀번호를 묻는다.GitHub는 공개키로 서명을 검증한다. 계정에 등록된 공개키로 서명을 확인하고, 짝이 맞으면 그 공개키가 등록된 계정을 요청자로 본다. 공개키와 개인키가 정확히 한 쌍이어야 이 검증이 통과한다.
저장소 접근 권한을 확인한다. 인증이 끝나면 GitHub는 그 계정이 요청한 private 저장소에 접근 권한이 있는지 본다. 권한이 있으면
git clone이 저장소 내용을 로컬로 복제한다.
인증과 권한은 따로 확인된다. 키 등록이 잘 되었어도 저장소에 초대받지 않은 계정이면 clone은 실패한다.
명령어만 모으면
cd ~/.ssh
ssh-keygen -t rsa -C "{git 계정 이메일}" -f "{키 이름}"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/{프라이빗키 이름}
cat {생성된 (공개)키 이름}.pub # 조회된 공개키 복사
# (GitHub에 공개키 등록)
git clone [email protected]:{private repository 소유자 이름}/{private repository 이름}.git
토큰을 URL에 넣는 방법도 있다
키 없이 Personal Access Token으로 clone하는 방법도 있다.
**[GitHub] → [Settings] → [Developer Settings]**의 Personal access tokens → Tokens (classic)에서 토큰을 발급한다.
토큰을 URL에 넣어 clone한다.
git clone https://{닉네임}:{토큰}@github.com/{저장소의 주인 닉네임}/{저장소 이름}.git
훨씬 간단하다. 처음 써 보고는 보안 측면에서 괜찮을지 의문이 들었는데, 걸리는 지점이 실제로 있다. URL에 넣은 토큰은 평문으로 남는다. clone에 쓴 URL은 그대로 .git/config의 remote.origin.url에 저장되고 셸 히스토리에도 남는다. 한 번 쓰고 버릴 환경이 아니라면 SSH 키 쪽이 낫다고 본다.
정리
공개키는 GitHub에 등록하고, 개인키는 로컬에만 둔다.
-f로 이름을 바꾼 키는ssh-add로 에이전트에 올려야 ssh가 쓴다.clone할 때 개인키는 전송되지 않는다. GitHub는 서명을 공개키로 검증해 계정을 찾고, 그 계정의 저장소 권한을 따로 확인한다.
토큰을 URL에 넣는 방법은 간단하지만 토큰이
.git/config와 셸 히스토리에 평문으로 남는다.