Vercel Sandbox 생성이 느려졌다면: 첫 작업까지 재고 오류 경계를 옮기자

Sandbox 생성 시간만 늘었다고 바로 성능 회귀로 판단하지 말자. 먼저 생성 시작부터 같은 첫 작업 완료까지 재고, 시작 실패를 잡는 위치가 Sandbox.create()인지 확인하면 된다. Vercel의 이번 변경은 스냅샷 복원 대기를 첫 작업에서 생성 단계로 옮긴다. 따라서 생성 지표와 첫 작업 지표가 서로 반대 방향으로 움직일 수 있다. 중요한 것은 대기 위치가 아니라 독자가 실제로 기다리는 전체 구간이다.

공식 발표일은 2026년 10월 8일이다. 이 글의 작성·검토일과 발표일은 다르며, 새 발표처럼 날짜를 바꾸지 않았다. 아래 비교는 공식 설명을 바탕으로 한 진단 설계다. 실측 로그나 실행 화면은 제공하지 않는다.

1. 달라진 것은 속도 약속보다 반환 시점이다

공식 변경 설명에 따르면 Sandbox.create()는 스냅샷 복원이 완료된 뒤에야 resolve한다. 반환된 Sandbox에서는 명령 실행과 파일 읽기·쓰기를 시작할 수 있고, 첫 명령이나 파일 작업이 복원을 다시 기다리는 구간은 사라진다. 동시에 시작 과정의 오류는 첫 작업 중에 나타나는 대신 생성 호출을 reject한다. 이것은 작업을 실행할 수 있는 준비 상태를 생성 API의 반환 경계에 맞춘 변경이다.

이전에는 생성 호출이 끝났다는 사실과 첫 작업이 곧바로 실행될 수 있다는 사실을 같게 해석하면 대기 원인을 잘못 분류할 수 있었다. 이제 복원 대기가 생성 구간에 포함된다. 다만 준비 상태는 명령의 성공, 애플리케이션의 정상 응답, 요청한 결과의 정확성까지 증명하지 않는다. 파일에 접근할 수 있다는 사실과 필요한 파일이 올바르게 존재한다는 사실도 구분해야 한다.

변경 전에는 첫 작업에서 복원을 기다리고 변경 후에는 복원 뒤 생성이 반환되는 개념 비교

스냅샷 복원 대기가 첫 작업에서 생성 완료 조건으로 이동한다. 행의 폭은 시간 비율을 나타내지 않는다. 출처: vercel.com/changelog/sandbox-create-waits-until-ready.

이 그림은 대기의 위치를 설명하는 개념 비교이며 시간축이나 벤치마크가 아니다. 두 줄의 폭으로 생성 시간이나 작업 시간의 비율을 읽어서는 안 된다. 변화의 핵심은 복원 완료를 어느 호출의 완료 조건에 포함하느냐에 있다.

2. 생성 지연만 보면 잘못된 경보를 만들 수 있다

Vercel은 생성 지연이 p50에서 약 50 ms 길어지고, 캐시되지 않은 스냅샷은 증가 폭이 더 클 수 있다고 보고했다. 반면 생성부터 첫 작업까지의 총시간은 같다고 설명했다. 이는 공급자 발표이며, 이 글에서 동일 환경으로 확인한 결과가 아니다. 표본 수와 분포 상세, 상위 백분위 지연은 발표에 제시되지 않았다.

p50은 중앙값에 해당하는 지표이지 최대 지연이나 모든 요청에 붙는 고정 비용이 아니다. 따라서 기존 타임아웃에서 무조건 50 ms를 빼거나 더하는 방식으로 대응할 근거는 없다. 캐시되지 않은 스냅샷의 증가 폭을 같은 숫자로 단정하는 것도 피해야 한다. 생성 구간만 비교해서 전체 요청이 느려졌다고 말하거나, 첫 작업 구간이 짧아졌다고 전체 처리량이 좋아졌다고 말하는 것은 모두 측정 경계가 다른 비교다.

생성 호출 직전부터 생성 완료를 거쳐 동일 첫 작업 완료까지를 비교하는 측정 경계

세 시점으로 생성·첫 작업·전체 구간을 분리한다. 약 50 ms는 공급자 보고의 생성 p50 변화이며 측정 결과나 최대 지연이 아니다. 출처: vercel.com/docs/sandbox/sdk-reference.

생성 시작부터 같은 첫 명령 또는 파일 작업이 완료될 때까지를 비교한다. 여기서 ‘같은’이 중요하다. 이전에는 버전 출력 명령을, 이후에는 패키지 설치를 첫 작업으로 삼았다면 두 값은 업데이트 효과를 비교하는 기준이 될 수 없다. 입력 스냅샷, 캐시 조건, 첫 작업의 내용 등 비교 조건을 기록하고 가능한 한 맞춘다. 다른 조건의 결과는 별도 묶음으로 읽는 것이 안전하다.

3. 두 구간을 기록하되 전체 구간을 판단 기준으로 둔다

새 진단 로그를 설계한다면 생성 직전, 생성 완료 직후, 첫 작업 완료 직후에 시각을 기록한다. 그러면 생성 구간, 첫 작업 구간, 둘을 합친 구간을 구분할 수 있다. 이는 편집자가 제안하는 관측 설계이며, 제품이 특정 로그 필드나 대시보드를 자동으로 제공한다는 뜻은 아니다. 숫자 예시를 만들어 업데이트 전후 실측처럼 보이게 하지도 않는다.

실제 로그에서 관찰할 상황 우선 해석 다음 확인
생성 구간은 길어지고 첫 작업 구간은 짧아지며 전체는 비슷함 공식 설명의 대기 경계 이동과 양립함 같은 작업·스냅샷·캐시 조건인지 확인
생성과 첫 작업의 전체 구간도 길어짐 대기 이동만으로 원인을 설명할 수 없음 작업 내용과 환경 차이를 별도로 조사
생성 호출이 실패하고 첫 작업 로그가 없음 시작 실패가 생성 경계에서 발생했을 가능성 생성 오류를 보존하고 명령 실패와 분류를 분리
생성은 성공했지만 첫 명령의 종료 코드가 실패 준비 상태와 명령 성공은 별개 명령 인자, 필요한 파일과 실행 결과를 확인

첫 번째 행도 원인을 확정하는 증거는 아니다. 여러 조건이 동시에 바뀌었다면 같은 모양의 로그가 나올 수 있다. 두 번째 행에서는 공식 발표의 ‘전체 시간은 같다’를 개별 환경의 보증처럼 사용하지 않는다. 이 표의 가치는 자동 결론을 내리는 것이 아니라, 지표를 잘못 묶어서 원인 조사를 건너뛰지 않게 하는 데 있다.

4. 시작 실패와 작업 실패를 다른 경계에서 처리한다

시작 오류가 생성 단계로 이동했으므로, 기존에 첫 명령만 감싸던 오류 처리와 알림 분류를 검토할 이유가 있다. 생성이 실패하면 사용할 Sandbox가 없으므로 첫 명령을 계속 실행하는 경로와 분리해야 한다. 생성 성공 뒤 명령이 실패한 경우에는 명령의 결과와 종료 코드를 확인하는 별도 경로가 필요하다. 다음 그림은 이 구분을 위한 편집자 설계이며 공식 오류 코드 목록은 아니다.

생성 실패는 별도 분류하고 생성 성공 후 명령 종료를 확인하며 detached는 wait로 기다리는 판단표

시작 실패와 생성 성공 뒤의 명령 실패를 분리한다. detached 완료 확인에는 wait()가 필요하며 non-detached runCommand는 자동으로 기다린다. 출처: vercel.com/docs/sandbox/sdk-reference.

특히 detached 명령은 ‘명령을 시작했다’와 ‘명령이 끝났다’를 구분한다. 공식 SDK 문서는 detached 명령의 완료와 종료 코드를 얻으려면 wait()를 사용하라고 설명한다. non-detached 명령은 runCommand()가 완료를 기다린다. 그러므로 전체 구간의 끝점을 detached 명령을 시작한 시각에 놓으면 완료까지의 지연을 재는 것이 아니다. 종료를 기다린 뒤 결과를 판단해야 준비 상태와 완료 상태를 혼동하지 않는다.

오류 경계를 나누는 것이 무조건 재시도하라는 권고는 아니다. 이 발표는 새로운 자동 재시도 정책이나 멱등성을 보장하지 않는다. 재시도를 설계할 때는 첫 작업이 외부 시스템을 바꾸는지와 중복 실행의 영향을 별도로 검토해야 한다. 이미 끝난 작업을 다시 시작할 위험은 생성 API의 준비 상태 변경만으로 해결되지 않는다.

5. 준비 완료는 인증·네트워크·비용 승인이 아니다

공식 문서의 SDK 시작 안내에는 프로젝트를 연결하고 환경변수를 받아 OIDC 토큰을 읽도록 하는 인증 절차가 나온다. 이번 반환 시점 변경을 인증 절차가 없어졌다는 뜻으로 읽어서는 안 된다. 토큰 자체를 진단 로그에 남기기보다 실패 단계와 필요한 상태를 구분하는 방식으로 설계한다. 이는 편집자의 안전한 기록 제안이지 새 제품 기능 주장과는 다르다.

네트워크 역시 별도다. 동결 SDK 문서에 따르면 기본 networkPolicy는 allow-all이다. Sandbox가 준비됐다는 응답은 외부 통신이 차단됐다는 증거가 아니다. 민감한 데이터를 넣거나 외부 요청을 실행하기 전에 필요한 송신 정책을 별도로 확인해야 한다. 격리된 실행 환경이라는 설명과 현재 작업에 승인된 네트워크 권한은 같은 질문이 아니다.

준비 완료와 별개로 확인해야 하는 명령 결과 인증 송신 정책 비용의 세 가지 경계

준비 완료는 실행 결과·인증·네트워크·비용 승인을 대신하지 않는다. 동결 SDK 문서의 기본 송신 정책은 allow-all이다. 출처: vercel.com/docs/sandbox/sdk-reference.

발표는 이번 변경이 자동 적용되며 SDK 업그레이드나 설정 변경이 필요하지 않다고 설명한다. 이는 이 업데이트를 적용하기 위한 요구사항에 관한 설명이지, 모든 SDK 관리가 앞으로 불필요하다는 말은 아니다. 새로운 무료 사용량, 과금 절감, 타임아웃 연장도 이 발표에서 확인되지 않는다. 속도·비용·권한상의 이득을 하나의 ‘ready’ 응답에 묶어서 설명하지 않는 것이 이번 변경을 정확히 적용하는 방법이다.

6. 지금 바꿀 것은 진단 기준과 실패 분류다

실무에서는 먼저 전체 구간의 정의를 맞추고, 생성 실패가 첫 작업의 오류 처리 밖으로 빠져나가지 않는지 확인하자. detached 작업을 쓰는 경로는 완료 시각의 기준도 점검한다. 생성 지연 하나만 달라진 상황과 전체 작업 완료가 늦어진 상황을 나눈 뒤, 후자의 원인을 별도로 조사하면 된다. 전체가 같다는 공식 설명을 모든 환경의 보증으로 확대하지 않고, 생성만 늘었다는 지표를 곧바로 회귀로 단정하지 않는 것이 균형 잡힌 판단이다.

이 글은 공식 발표와 문서를 해석한 진단 설계이며, 실제 Sandbox 실행이나 독립 성능 측정 결과가 아니다. 앱 상태 검사, 결과 검증, 인증, 송신 정책, 비용 검토는 여전히 별도다. 기존 블로그의 관련 글 본문과 정확한 링크를 이번 동결 자료만으로 검증할 수 없어 내부 링크를 임의로 추가하지 않았다.

참고한 공식 자료:

댓글

이 블로그의 인기 게시물

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

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

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