Vercel CLI 55: 이제 --yes는 배포 대상을 추측하지 않는다

테크
조회 2

CI가 초록색이어도 잘못된 팀의 동명 프로젝트로 배포했다면 성공이 아니다. 코딩 에이전트가 vercel --yes를 실행해 새 프로젝트를 만들어 버리면 빠른 자동화가 아니라 빠른 사고다. Vercel CLI 55는 이 모호함을 끊었다. 여러 팀이 있는 비대화형 환경에서 팀 신호가 없으면 더 이상 전역 선택값을 추측하지 않고 action_required: missing_scope로 멈춘다. 이번 변화의 핵심은 플래그 하나가 아니라 “배포 대상도 코드와 같은 입력 계약”이라는 운영 원칙이다.

Vercel CLI 55의 비대화형 링크 흐름을 명시적 팀 선택, 명시적 프로젝트 선택, 안전한 실패, 검증 가능한 배포의 네 단계로 보여주는 다이어그램
CLI 55의 핵심은 자동화가 덜 편해진 것이 아니라, 배포 대상이 입력 계약으로 승격됐다는 점이다.

무엇이 바뀌었나: --yes는 확인만 답하고 팀은 고르지 않는다

Vercel의 7월 15일 변경 로그와 vercel@55.0.0 릴리스 노트에 따르면 vercel link, deploy, pull, dev, git connect는 모두 같은 순서로 동작한다. 먼저 팀을 결정하고, 그 팀 안에서만 프로젝트를 찾는다. 과거처럼 계정의 모든 팀을 훑거나 vc switch의 전역 선택값을 비대화형 실행의 근거로 삼지 않는다.

팀 신호는 --team 또는 --scope, vercel.jsonscope, VERCEL_ORG_ID, 혹은 접근 가능한 팀이 하나뿐인 경우다. 여러 팀이 있는데 이 신호가 없으면 비대화형 명령은 프로젝트 검색·생성이나 기존 링크 파일 삭제 전에 안전하게 실패한다.

--yes의 의미도 좁아졌다. 확인 질문에는 기본 답을 주지만 “어느 팀인가” 같은 데이터 질문을 대신 결정하지 않는다. 프로젝트 이름을 --projectVERCEL_PROJECT_ID로 명시해도 소유 팀이 모호하면 팀 계약은 별도로 필요하다.

왜 중요한가: 배포 대상 추측은 편의가 아니라 숨은 상태다

로컬 터미널에서는 사람이 picker를 보고 실수를 고칠 수 있다. CI runner, 임시 컨테이너, 코딩 에이전트, cron job에는 그런 맥락이 없다. 전역 로그인 상태나 마지막 vc switch 선택은 실행 정의에 보이지 않으며 runner 재사용, 계정 변경, 새 팀 추가만으로 결과가 달라질 수 있다.

특히 조직마다 같은 프로젝트 이름을 쓰거나 monorepo가 여러 Vercel Project를 갖는 환경에서는 “폴더명과 비슷한 프로젝트”가 충분한 식별자가 아니다. 성공한 command exit code가 올바른 owner와 project를 보장하지 않으면 배포 자동화의 가장 중요한 postcondition이 빠져 있다.

CLI 55는 모호할 때 실패하도록 바꿨다. 파이프라인을 한 번 깨뜨릴 수 있지만, 잘못된 프로젝트 생성·환경 변수 pull·production deploy를 조용히 허용하는 것보다 복구 범위가 작다. 이는 fail-fast보다 더 정확히 말해 fail-closed 대상 해석이다.

CI와 에이전트의 최소 계약: owner와 project를 한 쌍으로 고정한다

가장 결정적인 경로는 VERCEL_ORG_IDVERCEL_PROJECT_ID를 함께 제공하는 것이다. 릴리스 노트는 두 값이 있으면 vercel link가 정확히 그 owner-project 쌍을 확인하고 prompt 없이 처리하며, 해석할 수 없는 쌍은 다른 후보로 fallback하지 않는다고 설명한다.

사람이 읽기 쉬운 설정이 필요하면 vercel pull --team your-team-slug처럼 team/scope를 명시하고 project를 별도 플래그로 준다. 토큰은 인증 수단이고 target selector가 아니다. “이 token이 어느 팀에 접근 가능한가”와 “이번 job이 어느 팀에 배포해야 하는가”를 분리해야 한다.

에이전트 tool wrapper도 자유 문자열 shell보다 구조화된 입력을 받아야 한다. 예를 들어 deploy({ orgId, projectId, environment, commitSha })처럼 필수 필드를 만들고, production은 allowlist와 승인 단계를 추가한다. prompt에 프로젝트명을 적는 것만으로는 실행 계약이 아니다.

업그레이드 순서: pin, dry-run, verify

먼저 현재 파이프라인이 Vercel CLI를 global latest로 즉시 당기는지, lockfile에 pin하는지 확인한다. CLI 55는 major release이므로 자동 업그레이드보다 preview branch에서 링크·pull·build·deploy 경로를 재현하는 편이 안전하다.

그다음 모든 비대화형 명령에서 target signal을 표로 만든다. job별 expected org, project, environment, root directory를 기록하고 secret store에는 ID를, 읽기 쉬운 config에는 slug를 둘 수 있다. monorepo라면 앱별 working directory와 project ID 매핑을 함께 검증한다.

마지막으로 배포 뒤 URL만 확인하지 말고 deployment metadata의 owner/project/environment와 기대값을 비교한다. missing_scope는 재시도로 해결할 transient error가 아니다. 입력 누락으로 분류해 즉시 실패시키고, 자동으로 임의 scope를 채우지 않는다.

커뮤니티 신호: 오래된 질문은 “프로젝트를 어떻게 지정하나”였다

Vercel Community에는 vercel pull이 특정 프로젝트 환경을 어떻게 가져오는지 문서가 불명확하다는 질문과 VERCEL_PROJECT_ID 사용법이 공유돼 왔다. 과거 GitHub 토론과 monorepo 사례에서도 --yes, --scope, --project 조합을 둘러싼 혼선이 반복됐다. 이 글은 커뮤니티를 기능 사실의 근거가 아니라, 숨은 scope가 어떤 인지 비용을 만들었는지 보여주는 신호로만 사용한다.

CLI 55는 그 불편을 “더 영리한 추측”으로 해결하지 않았다. 추측을 제거하고 owner를 먼저 고르는 방식으로 바꿨다. 자동화 사용자에게 필요한 것은 항상 성공하는 명령이 아니라, 잘못된 대상에는 성공할 수 없는 명령이라는 판단이 반영됐다.

실무적으로는 문서와 사내 runbook도 바뀌어야 한다. vercel --yes만 복사한 예시는 이제 충분하지 않다. 어떤 계정·팀·프로젝트·환경을 의도하는지 함께 보여주는 예시가 재현 가능한 예시다.

오늘 적용할 실무 체크리스트

1. CI와 agent workflow에서 vercel link, pull, deploy, dev, git connect 호출을 전수 검색한다.

2. Vercel CLI 버전을 확인하고 55 업그레이드는 preview branch에서 리허설한다.

3. 비대화형 job마다 VERCEL_ORG_IDVERCEL_PROJECT_ID를 한 쌍으로 설정한다.

4. 이름 기반 구성이 필요하면 --team/--scope--project를 모두 명시한다.

5. token을 target selector로 간주하지 말고 최소 권한 인증 수단으로만 취급한다.

6. monorepo의 app path → org/project ID 매핑을 코드 리뷰 가능한 설정으로 둔다.

7. action_required: missing_scope를 재시도하지 않고 configuration error로 분류한다.

8. production deploy 전 allowlist와 사람 승인 또는 정책 검사를 둔다.

9. 배포 후 owner, project, environment, commit SHA를 기대값과 비교한다.

10. rollback도 같은 target ID 계약을 사용해 다른 프로젝트를 되돌리는 사고를 막는다.

리스크와 반론

명시적 ID는 secret 관리와 환경별 설정을 늘린다. 하지만 그 복잡성은 원래 존재하던 배포 대상을 보이게 만든 것이다. ID가 민감한 credential은 아니더라도 token과 함께 secret store에서 관리하면 로그·복사 오류를 줄일 수 있다.

팀이 하나뿐이면 변화가 거의 느껴지지 않을 수 있다. 그러나 자동화 템플릿이 나중에 여러 팀 계정으로 복제될 수 있으므로 target을 처음부터 명시하면 환경 확장 시 동작이 바뀌지 않는다.

마지막으로 CLI 55가 모든 오배포를 막지는 않는다. 올바르지만 잘못 입력된 ID, 과도한 token 권한, 잘못된 production flag는 여전히 위험하다. 이번 변경은 대상 해석을 결정적으로 만들 뿐, 승인·권한·사후 검증을 대체하지 않는다.

비대화형 배포의 최소 입력 계약

# Pin the exact owner-project pair in CI
export VERCEL_ORG_ID="$VERCEL_ORG_ID"
export VERCEL_PROJECT_ID="$VERCEL_PROJECT_ID"

vercel pull --yes --environment=preview --token="$VERCEL_TOKEN"
vercel build --token="$VERCEL_TOKEN"
vercel deploy --prebuilt --token="$VERCEL_TOKEN"

ID는 출력하지 말고, 오류 로그에는 값 대신 expected target의 별칭과 검증 결과만 남긴다.

Vercel CLI 55 전환 체크포인트

CI와 agent workflow에서 vercel link, pull, deploy, dev, git connect 호출을 전수 검색한다.

Vercel CLI 버전을 확인하고 55 업그레이드는 preview branch에서 리허설한다.

비대화형 job마다 VERCEL_ORG_IDVERCEL_PROJECT_ID를 한 쌍으로 설정한다.

이름 기반 구성이 필요하면 --team/--scope--project를 모두 명시한다.

token을 target selector로 간주하지 말고 최소 권한 인증 수단으로만 취급한다.

monorepo의 app path → org/project ID 매핑을 코드 리뷰 가능한 설정으로 둔다.

action_required: missing_scope를 재시도하지 않고 configuration error로 분류한다.

production deploy 전 allowlist와 사람 승인 또는 정책 검사를 둔다.

배포 후 owner, project, environment, commit SHA를 기대값과 비교한다.

rollback도 같은 target ID 계약을 사용해 다른 프로젝트를 되돌리는 사고를 막는다.

정리

Vercel CLI 55의 breaking change는 --yes를 약하게 만든 것이 아니라 자동화를 더 결정적으로 만들었다. 팀과 프로젝트를 명시하고, 모호함은 missing_scope로 실패시키며, 배포 뒤 실제 target을 검증하라. 그러면 CI와 에이전트는 “어딘가에 배포하는 shell”이 아니라 검토 가능한 deployment control plane이 된다.

출처

다른 글