개인 로그인 없는 Copilot SDK: 조직 인증·1시간 토큰 갱신·청구를 나눠 점검하기

야간에 돌려 둔 Copilot SDK 작업이 담당자의 로그인 상태에 기대고 있다면, 작업을 옮기거나 담당자가 바뀔 때 인증 책임도 함께 흔들린다. 이번 변화의 핵심은 “로그인 없이 아무나 호출한다”가 아니다. 개인 대신 조직에 설치된 GitHub App의 신원으로 요청하고, 그 설치를 소유한 조직에 사용량과 청구를 연결하는 경로가 생겼다는 것이다. 운영자가 먼저 나눠 볼 질문은 세 가지다. 어디서 실행하는가, 새 토큰은 어느 프로세스에 전달하는가, 비용은 어느 조직에 귀속되는가.

GitHub는 2026년 10월 27일 이 서버 간 인증을 공개 프리뷰로 발표했다. 이 글은 10월 28일 수집·보존한 발표와 SDK 인증 문서를 기준으로 한다. 10월 29일은 글의 공개 예정일이며 기능 발표일이나 예약 완료 시각이 아니다. 공개 프리뷰라는 범위와 조직별 활성화 조건이 남아 있으므로, 발표만 보고 자신의 조직에서도 곧바로 호출된다고 판단하면 안 된다.

1. 실행 위치부터 고르면 불필요한 비밀 관리가 줄어든다

아래 표는 공식 문서를 운영자의 선택 순서로 재구성한 것이다. GitHub Actions 안에서 실행하는 작업과 외부 서버·다른 CI의 작업을 하나의 설정 예제로 합치면 권한 이름부터 어긋난다.

실행 위치 먼저 고를 인증 경로 필요한 확인 혼동하지 말 것
조직 소유 저장소의 GitHub Actions 내장 GITHUB_TOKEN 워크플로 copilot-requests: write, 조직의 Allow use of Copilot CLI billed to the organization 정책 문서의 이 경로에는 별도 GitHub App이나 저장된 인증 비밀이 필요하지 않다
Actions 밖의 서비스·다른 CI 조직 설치 GitHub App의 단기 설치 토큰 조직 Copilot Requests: Read-only, 설치 대상 조직, 해당 인증 방식 활성화 Actions의 write 설정을 App 조직 권한에 그대로 옮기지 않는다
이미 떠 있는 런타임에 연결하는 SDK 런타임 프로세스에 토큰 설정 런타임의 COPILOT_GITHUB_TOKEN 및 갱신 후 재시작 대상 연결하는 클라이언트의 환경 변수만 바꿨다고 기존 런타임에 반영됐다고 보지 않는다
조직 저장소 Actions의 내장 토큰과 외부 CI의 조직 설치 App 토큰을 두 열로 비교한 인증 경로도

Actions의 write와 App의 Read-only는 서로 다른 설정 면이다. 공식 문서를 재구성한 자체 판단도이며 제품 화면이 아니다. 출처: github.blog/changelog/2026-10-27-github-copilot-supports-server-to-server-authentication.

Actions의 copilot-requests: write와 GitHub App의 Copilot Requests: Read-only는 서로 다른 설정 면의 값이다. 하나가 다른 하나의 오탈자나 더 강한 대안이 아니다. 외부 CI에서 시작한다면 App을 만들고, 사용량을 귀속시킬 조직에 설치하고, 필요한 Copilot 권한을 포함한 설치 토큰을 발급하는 순서다. 반대로 조직 저장소의 Actions에서 처리할 수 있는 작업이라면, 별도 App 비밀을 늘리기 전에 문서의 내장 토큰 경로가 맞는지 먼저 판단하는 편이 합리적이다. 이는 경로 선택에 관한 편집 분석이며 실제 계정의 사용 가능 여부를 인증한 결론은 아니다.

2. 개인 로그인 차단과 토큰 전달은 한 쌍이다

환경 변수에 토큰이 있다는 사실과 SDK가 그 토큰을 사용한다는 사실은 다르다. 공식 문서에서 useLoggedInUser: false는 저장된 사용자 인증뿐 아니라 환경 변수 토큰을 포함한 자동 자격 증명 탐색도 끈다. 따라서 자식 런타임을 만드는 구성에서 이 옵션만 꺼 놓고 COPILOT_GITHUB_TOKEN에 의존하는 예제를 “조직 토큰 설정 완료”라고 제시하면 안 된다.

보존한 TypeScript 예제의 요지는 설치 토큰을 gitHubToken에 직접 넘기면서 useLoggedInUser: false를 함께 지정하는 것이다. Python은 github_token과 use_logged_in_user=False라는 표기를 사용한다. 언어별 옵션 이름을 섞지 않는 것도 중요하다. 여기서는 실제 발급 코드나 비밀 값을 제공하지 않으며, 아래는 실행 가능한 전체 프로그램이 아니라 전달 위치를 비교하는 설명이다.

런타임 형태 토큰 전달 위치 새 토큰으로 교체할 대상
SDK가 띄운 자식 프로세스 SDK의 명시적 토큰 옵션 새 토큰으로 SDK 클라이언트 재시작
인프로세스 FFI 같은 명시적 토큰 옵션 새 토큰으로 호스트 런타임 재시작
기존 런타임 URI에 연결 기존 런타임 프로세스의 COPILOT_GITHUB_TOKEN 새 토큰으로 호스트 런타임 재시작
자식 및 인프로세스 SDK의 명시적 토큰 옵션과 기존 런타임 환경 변수의 전달 위치를 구분한 구조도

개인 로그인 자동 탐색을 끈 SDK에는 명시적 옵션으로 토큰을 전달한다. 기존 런타임은 그 런타임 프로세스의 환경 설정과 구분한다. 출처: docs.github.com/en/copilot/how-tos/copilot-sdk/auth/server-to-server-tokens.

이 구분은 장애를 찾을 때도 유용하다. “토큰을 넣었는데 인증되지 않는다”면 먼저 어느 프로세스의 환경에 넣었는지, 실제 생성자 옵션으로 전달했는지, 자동 탐색을 껐는지를 같은 실행 경로 안에서 대조한다. 개인 세션으로 우연히 성공한 요청은 조직 설치 인증이 동작한다는 증거가 될 수 없다. 개인 로그인 폴백을 차단하는 설정은 인증 주체를 분명히 하기 위한 것이지, 에이전트가 실행하는 명령을 안전하게 만드는 격리 장치가 아니다.

3. 한 시간 토큰은 발급보다 교체 절차가 중요하다

설치 토큰은 한 시간 뒤 만료된다. 공식 문서는 현재 토큰이 만료되기 전에 새 설치 토큰을 발급하고, 자식 프로세스 구성이라면 새 토큰으로 SDK 클라이언트를 재시작하라고 설명한다. 인프로세스 또는 기존 런타임 구성에서는 호스트 런타임을 새 토큰으로 재시작하는 경로다. 자동으로 토큰이 내부 갱신된다거나, 실행 중인 모든 세션에 무중단으로 새 토큰이 주입된다는 보장은 이 문서에 없다.

한 시간 수명의 설치 토큰을 발급하고 만료 전에 새로 발급한 뒤 SDK 또는 호스트를 재시작하는 순서도

한 시간은 토큰 수명이다. 개념 순서도이며 실행 시간 측정이나 무중단 교체 보장이 아니다. 새 토큰으로 해당 클라이언트 또는 호스트를 재시작한다. 출처: docs.github.com/en/copilot/how-tos/copilot-sdk/auth/server-to-server-tokens.

운영 설계에서 따로 정해야 할 부분은 “재시작할 때 진행 중인 작업을 어떻게 다룰 것인가”다. 예를 들어 긴 작업을 중단 가능한 단위로 나눌지, 경계에서 새 클라이언트로 넘길지, 실패한 작업을 어디서 재개할지는 애플리케이션의 책임으로 남는다. 이것은 공식 SDK가 그런 복구 기능을 제공한다는 설명이 아니라, 토큰 만료와 프로세스 재시작 요구에서 도출한 설계 질문이다. 토큰을 새로 받는 것과 기존 작업이 이어지는 것을 한 가지 성공 조건으로 묶지 않는 것이 핵심이다.

정확한 교체 여유 시간을 여기서 임의로 고정하지도 않는다. 공식 본문이 제시한 수치는 한 시간의 수명이며, 모든 서비스에 적용되는 갱신 간격이나 중단 시간 측정치는 없다. 운영자는 발급·만료 정보를 다루는 방식과 재시작 정책을 자신의 실행 구조에 맞춰 검증해야 한다. 토큰 원문이나 App 비밀을 진단 로그에 남기는 대신, 비밀이 아닌 실행 경로·설치 대상·실패 시점으로 원인을 좁히는 방식이 적절하다.

4. 인증 오류, 정책 거부, 잘못된 청구를 분리하는 진단표

“조직 인증이 안 된다”는 한 문장으로 모든 문제를 묶으면 권한을 불필요하게 넓히기 쉽다. 다음은 공식 Troubleshooting 항목을 확인 질문으로 바꾼 자료다. 같은 HTTP 상태여도 응답의 설명이 다르므로 상태 코드 하나로 조치를 확정하지 않는다.

관찰한 증상 먼저 확인할 경계 다음 판단
401 Unauthorized 토큰 유효성·만료 새 설치 토큰을 발급하고 올바른 전달·재시작 경로인지 확인한다
App 설치 토큰 요청이 활성화되지 않았다는 403 조직의 해당 인증 지원·활성화 토큰만 재발급하지 말고 조직이 이 경로를 지원하는지 확인한다
Not authenticated 또는 OAuth/HMAC 키 없음 명시적 옵션·자동 탐색 useLoggedInUser: false에서 환경 변수만 기대한 것은 아닌지 대조한다
Copilot API의 403 Forbidden 설치에 부여된 Copilot 조직 권한 필요한 권한을 확인한 뒤 새 토큰을 발급한다
요청한 모델을 사용할 수 없음 조직 모델 정책·번들 런타임 지원 인증 성공과 모델 사용 가능성을 별도로 확인한다
다른 계정에 청구됨 App 설치 소유 조직 작업 이름이 아니라 설치가 속한 조직을 확인한다
인증 누락과 권한 거부, 모델 사용 불가와 청구 주체 오류를 별도 확인 경계로 구분한 진단도

같은 실패로 묶지 않고 응답의 설명을 대조한다. Read-only라는 Copilot 권한은 에이전트 명령의 읽기 전용 실행 보장이 아니다. 출처: docs.github.com/en/copilot/how-tos/copilot-sdk/auth/server-to-server-tokens.

이 표의 목적은 곧바로 재시도나 권한 추가를 지시하는 것이 아니라, 잘못된 경계를 바꾸지 않도록 하는 데 있다. 조직 활성화 문제를 새 토큰 발급으로 해결할 수는 없고, 모델 정책 거부를 개인 로그인 폴백으로 우회하면 원하는 조직 신원이라는 목표부터 흐려진다. “Read-only”라는 단어 역시 이 이름의 Copilot 요청 권한을 가리킬 뿐, 에이전트의 파일 수정·명령 실행까지 읽기 전용으로 제한한다는 뜻이 아니다.

5. 청구와 중단 책임까지 조직으로 연결하기

App 설치 경로의 사용량과 청구는 설치를 소유한 조직에 귀속되며, 그 조직의 모델 정책·예산·지출 통제가 적용된다. 따라서 개인 인증을 없애는 작업은 비용을 없애는 작업이 아니다. 이번 발표는 새로운 무료 사용량이나 단가 인하를 보장하지 않는다. 외부 CI의 실행 계정 이름이 맞더라도 App이 다른 조직에 설치돼 있으면 의도한 청구 주체와 어긋날 수 있다.

조직 소유자는 접근 가능한 App을 검토하고, AI 사용량 CSV의 app_client_id로 App에 귀속된 사용량을 구분할 수 있다. 접근을 중단할 때는 App을 일시 중지하거나 제거하는 경로가 제시돼 있다. 다만 본문은 중단이 전파되는 정확한 시간을 제시하지 않으므로 “즉시 모든 실행 종료”처럼 확대해 해석하지 않는다. 요청 신원·비용 관찰·접근 중단 경로가 연결돼 있다는 점과, 이미 돌아가는 작업의 수명 관리가 해결됐다는 주장은 구분해야 한다.

이 글은 보존한 공식 본문을 재구성한 운영 판단 자료이며, 실제 GitHub App 설치·SDK 요청·토큰 갱신·청구 대조를 실행한 결과가 아니다. 조직마다 활성화와 모델 정책이 다를 수 있고, 공개 프리뷰의 현재 조건을 실제 도입 전에 다시 확인할 필요가 있다. 결론은 간단하다. 개인 로그인에서 벗어나는 기준은 “토큰 발급 성공” 하나가 아니라, 실행 위치에 맞는 인증 경로·명시적인 전달·만료 전 교체와 재시작·설치 조직의 청구를 각각 설명할 수 있는 상태다.

함께 읽기

출처

댓글

이 블로그의 인기 게시물

체크아웃은 분리됐는데 Git 상태는 공유된다: Codex 0.154 worktree의 세 경계

잠근 작업이 커밋 뒤 다시 나온다: PostgreSQL 에이전트 큐의 소유권 설계

코딩 에이전트는 API 문서보다 AGENTS.md를 먼저 읽었다