{"componentChunkName":"component---src-templates-blog-post-js","path":"/etc/Vercel-계정-정지로-블로그가-내려갔다-다른-계정으로-재배포하고-도메인-옮기기/","result":{"data":{"site":{"siteMetadata":{"title":"Bottlehs Tech Blog","description":"웹·앱·AI 개발자 전병훈(bottlehs)의 기술 블로그. AI·LLM, JavaScript·Vue, Spring Boot, 알고리즘, 블록체인 실무 가이드를 다룹니다","siteUrl":"https://www.bottlehs.dev","author":{"name":"Jeon Byung Hun","summary":"개발을 즐기는 bottlehs - Engineer, MS, AI, FE, BE, OS, IOT, Blockchain, 설계, 테스트"},"social":{"github":"bottlehs","codepen":"bottlehs"}}},"markdownRemark":{"id":"56d96e1d-d637-50eb-9339-744134d543d3","excerpt":"도메인 만료로 블로그를 한 번 잃고 새 도메인으로 옮긴 지 한 달 만에, 이번에는 호스팅 계정이 정지됐다. 사이트 주소를 열면 Vercel이  와  라는 에러 코드만 돌려줬다. 코드도, DNS…","html":"<p>도메인 만료로 블로그를 한 번 잃고 새 도메인으로 옮긴 지 한 달 만에, 이번에는 <strong>호스팅 계정이 정지</strong>됐다. 사이트 주소를 열면 Vercel이 <code class=\"language-text\">402 Payment Required</code> 와 <code class=\"language-text\">DEPLOYMENT_DISABLED</code> 라는 에러 코드만 돌려줬다. 코드도, DNS도, 도메인도 멀쩡했지만 배포를 실행하는 계정이 막히니 모든 것이 한 번에 멈췄다.</p>\n<p>이 글은 정지된 계정을 되살리는 대신 <strong>같은 코드를 다른 Vercel 팀으로 옮겨 재배포하고, 도메인을 새 프로젝트로 넘긴 과정</strong>을 순서대로 정리한 기록이다. 중간에 두 번 막혔던 지점(팀 기본값으로 켜진 접근 보호, 도메인 검증 대기 상태)도 원인과 함께 남긴다. Gatsby 정적 사이트 기준이지만 Next.js 등 다른 프레임워크도 절차는 같다.</p>\n<h2 id=\"증상-402-응답과-deployment_disabled\" style=\"position:relative;\"><a href=\"#%EC%A6%9D%EC%83%81-402-%EC%9D%91%EB%8B%B5%EA%B3%BC-deployment_disabled\" aria-label=\"증상 402 응답과 deployment_disabled permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>증상: 402 응답과 DEPLOYMENT_DISABLED</h2>\n<p>브라우저에서는 그냥 흰 화면에 짧은 안내만 보였다. 원인을 좁힐 때는 응답 헤더를 봐야 한다. Vercel은 플랫폼 수준의 에러를 <code class=\"language-text\">x-vercel-error</code> 헤더에 적어 준다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sS</span> <span class=\"token parameter variable\">-D</span> - <span class=\"token parameter variable\">-o</span> /dev/null https://www.bottlehs.dev/\n<span class=\"token comment\"># HTTP/2 402</span>\n<span class=\"token comment\"># server: Vercel</span>\n<span class=\"token comment\"># x-vercel-error: DEPLOYMENT_DISABLED</span></code></pre></div>\n<p>Vercel 에러 코드는 범위가 분명하다.</p>\n<table>\n<thead>\n<tr>\n<th>에러 코드</th>\n<th>상태</th>\n<th>뜻</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"language-text\">DEPLOYMENT_DISABLED</code></td>\n<td>402</td>\n<td>계정·팀 문제로 배포가 비활성화됨</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">DEPLOYMENT_NOT_FOUND</code></td>\n<td>404</td>\n<td>요청한 호스트에 연결된 배포가 없음</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">DEPLOYMENT_BLOCKED</code></td>\n<td>403</td>\n<td>정책 위반 등으로 배포가 차단됨</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">NOT_FOUND</code></td>\n<td>404</td>\n<td>배포는 있지만 해당 경로가 없음</td>\n</tr>\n</tbody>\n</table>\n<p><code class=\"language-text\">DEPLOYMENT_DISABLED</code>는 코드나 DNS로 고칠 수 있는 문제가 아니다. 계정이 풀릴 때까지 기다리거나, 다른 계정(팀)으로 옮겨야 한다. 정적 블로그는 서버 상태가 없으므로 옮기는 쪽이 빠르다.</p>\n<h2 id=\"옮기기-전에-챙길-것\" style=\"position:relative;\"><a href=\"#%EC%98%AE%EA%B8%B0%EA%B8%B0-%EC%A0%84%EC%97%90-%EC%B1%99%EA%B8%B8-%EA%B2%83\" aria-label=\"옮기기 전에 챙길 것 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>옮기기 전에 챙길 것</h2>\n<p>정지된 팀의 대시보드와 API는 <strong>읽기조차 안 되는 경우가 많다</strong>. 실제로 CLI 토큰은 <code class=\"language-text\">Not authorized</code> 를 돌려줬다. 그러니 옮기기 전에 “옛 프로젝트에만 있던 설정”이 무엇인지 떠올려야 한다.</p>\n<ol>\n<li><strong>환경 변수</strong>: 옛 프로젝트에서 꺼낼 수 없다. 코드에서 <code class=\"language-text\">process.env</code> 를 읽는 곳을 모두 찾아 어떤 값이 필요한지 목록을 만든다.</li>\n<li><strong>빌드 설정</strong>: 프레임워크, 빌드 명령, 출력 폴더, Node 버전. <code class=\"language-text\">vercel.json</code> 과 <code class=\"language-text\">package.json</code> 의 <code class=\"language-text\">engines</code> 에 적혀 있으면 새 프로젝트에서도 자동으로 적용된다.</li>\n<li><strong>도메인과 리다이렉트</strong>: 루트 → www 리다이렉트처럼 대시보드에서만 설정한 것이 있는지 확인한다. 코드(<code class=\"language-text\">vercel.json</code>)에 있으면 그대로 따라온다.</li>\n<li><strong>DNS 레코드 현재 값</strong>: 전환 중 비교하기 위해 <code class=\"language-text\">dig</code> 로 지금 값을 기록해 둔다.</li>\n</ol>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># 코드가 요구하는 환경 변수 목록</span>\n<span class=\"token function\">grep</span> <span class=\"token parameter variable\">-rn</span> <span class=\"token string\">\"process.env\"</span> gatsby-config.js gatsby-node.js src <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> <span class=\"token parameter variable\">-v</span> node_modules\n\n<span class=\"token comment\"># 현재 DNS</span>\n<span class=\"token function\">dig</span> +short www.bottlehs.dev CNAME\n<span class=\"token function\">dig</span> +short bottlehs.dev A</code></pre></div>\n<p>이 블로그는 지난 도메인 이전 때 <strong>설정을 코드 기본값으로 모아 두고, 환경 변수는 덮어쓰기 용도로만 쓰는 구조</strong>로 바꿔 두었다. 그래서 새 프로젝트에 등록해야 할 변수는 애드센스 광고 단위를 끄는 <code class=\"language-text\">GATSBY_ADSENSE_UNITS=off</code> 하나뿐이었다. 이 결정이 이번 이전을 30분짜리 작업으로 만들었다.</p>\n<h2 id=\"1단계-cli-로그인을-새-팀으로-바꾼다\" style=\"position:relative;\"><a href=\"#1%EB%8B%A8%EA%B3%84-cli-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%84-%EC%83%88-%ED%8C%80%EC%9C%BC%EB%A1%9C-%EB%B0%94%EA%BE%BC%EB%8B%A4\" aria-label=\"1단계 cli 로그인을 새 팀으로 바꾼다 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1단계: CLI 로그인을 새 팀으로 바꾼다</h2>\n<p>Vercel CLI는 한 번에 한 계정으로만 로그인된다. 정지된 계정 토큰이 남아 있으면 모든 명령이 <code class=\"language-text\">Not authorized</code> 로 실패하므로 먼저 교체한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">vercel <span class=\"token builtin class-name\">logout</span>\nvercel login            <span class=\"token comment\"># 새 계정(팀)으로 로그인</span>\nvercel teams <span class=\"token function\">ls</span>         <span class=\"token comment\"># ✔ 표시가 새 팀에 있는지 확인</span></code></pre></div>\n<p>이후 명령에는 <code class=\"language-text\">--scope &lt;팀 슬러그></code> 를 붙여 어느 팀에서 실행하는지 명시하는 편이 안전하다. 기본 팀 설정에 의존하면 엉뚱한 팀에 프로젝트가 생길 수 있다.</p>\n<h2 id=\"2단계-옛-프로젝트-링크를-끊고-새-프로젝트를-만든다\" style=\"position:relative;\"><a href=\"#2%EB%8B%A8%EA%B3%84-%EC%98%9B-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%81%ED%81%AC%EB%A5%BC-%EB%81%8A%EA%B3%A0-%EC%83%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%A7%8C%EB%93%A0%EB%8B%A4\" aria-label=\"2단계 옛 프로젝트 링크를 끊고 새 프로젝트를 만든다 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2단계: 옛 프로젝트 링크를 끊고 새 프로젝트를 만든다</h2>\n<p>레포의 <code class=\"language-text\">.vercel/project.json</code> 에는 <strong>옛 팀 ID와 프로젝트 ID</strong>가 들어 있다. 이 상태로 배포하면 CLI가 정지된 프로젝트에 올리려다 실패한다. 폴더를 치우고 새로 연결한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">mv</span> .vercel /tmp/old-vercel-link        <span class=\"token comment\"># 복구용으로 보관</span>\nvercel <span class=\"token function\">link</span> <span class=\"token parameter variable\">--scope</span> bluebutton <span class=\"token parameter variable\">--project</span> blog <span class=\"token parameter variable\">--yes</span>\n<span class=\"token function\">cat</span> .vercel/project.json\n<span class=\"token comment\"># {\"projectId\":\"prj_새ID\",\"orgId\":\"team_새ID\",\"projectName\":\"blog\"}</span></code></pre></div>\n<p><code class=\"language-text\">--yes</code> 를 주면 같은 이름의 프로젝트가 없을 때 바로 생성한다. <code class=\"language-text\">.vercel</code> 은 <code class=\"language-text\">.gitignore</code> 에 있어야 하며, 커밋할 내용은 생기지 않는다.</p>\n<h2 id=\"3단계-환경-변수를-다시-등록한다\" style=\"position:relative;\"><a href=\"#3%EB%8B%A8%EA%B3%84-%ED%99%98%EA%B2%BD-%EB%B3%80%EC%88%98%EB%A5%BC-%EB%8B%A4%EC%8B%9C-%EB%93%B1%EB%A1%9D%ED%95%9C%EB%8B%A4\" aria-label=\"3단계 환경 변수를 다시 등록한다 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3단계: 환경 변수를 다시 등록한다</h2>\n<p>여기서 처음 막혔다. <code class=\"language-text\">GATSBY_</code> 처럼 프레임워크가 브라우저에 노출하는 접두사가 붙은 변수는 <strong>민감 정보(secret)로 등록할 수 없다</strong>.</p>\n<p><strong>나쁜 예시: 기본값으로 등록</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">printf</span> <span class=\"token string\">'off'</span> <span class=\"token operator\">|</span> vercel <span class=\"token function\">env</span> <span class=\"token function\">add</span> GATSBY_ADSENSE_UNITS production\n<span class=\"token comment\"># \"reason\": \"invalid_visibility\",</span>\n<span class=\"token comment\"># \"message\": \"Environment variables with a public framework prefix (GATSBY)</span>\n<span class=\"token comment\">#  cannot use secret visibility on Production or Preview.\"</span></code></pre></div>\n<p><strong>좋은 예시: 일반 변수로 명시</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token builtin class-name\">printf</span> <span class=\"token string\">'off'</span> <span class=\"token operator\">|</span> vercel <span class=\"token function\">env</span> <span class=\"token function\">add</span> GATSBY_ADSENSE_UNITS production <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">--visibility</span> config --no-sensitive\nvercel <span class=\"token function\">env</span> <span class=\"token function\">ls</span>\n<span class=\"token comment\"># GATSBY_ADSENSE_UNITS   Non-sensitive   Production</span></code></pre></div>\n<p>브라우저 코드에 포함되는 값은 어차피 공개되므로 일반 변수가 맞다. 비밀값(API 키 등)은 접두사 없이 서버 쪽에서만 읽도록 설계해야 한다.</p>\n<h2 id=\"4단계-프로덕션-배포\" style=\"position:relative;\"><a href=\"#4%EB%8B%A8%EA%B3%84-%ED%94%84%EB%A1%9C%EB%8D%95%EC%85%98-%EB%B0%B0%ED%8F%AC\" aria-label=\"4단계 프로덕션 배포 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4단계: 프로덕션 배포</h2>\n<p>이 블로그는 Git 연동 없이 CLI로 수동 배포한다. CLI는 <code class=\"language-text\">.vercelignore</code> 로 거른 소스만 올리고 빌드는 Vercel에서 한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">vercel deploy <span class=\"token parameter variable\">--prod</span> <span class=\"token parameter variable\">--scope</span> bluebutton <span class=\"token parameter variable\">--yes</span>\n<span class=\"token comment\"># Production  https://blog-xxxxxxxx-bluebutton.vercel.app</span>\n<span class=\"token comment\"># Building…</span>\n<span class=\"token comment\"># ...</span>\n<span class=\"token comment\"># status  ● Ready</span></code></pre></div>\n<p><code class=\"language-text\">.vercelignore</code> 에는 <code class=\"language-text\">node_modules</code>, 빌드 산출물(<code class=\"language-text\">public</code>, <code class=\"language-text\">.cache</code>), <code class=\"language-text\">.env*</code> 를 반드시 넣는다. 업로드가 200KB 남짓으로 끝났고, Node 24는 <code class=\"language-text\">package.json</code> 의 <code class=\"language-text\">engines</code> 로 자동 선택됐다.</p>\n<h2 id=\"5단계-팀-기본값으로-켜진-deployment-protection-끄기\" style=\"position:relative;\"><a href=\"#5%EB%8B%A8%EA%B3%84-%ED%8C%80-%EA%B8%B0%EB%B3%B8%EA%B0%92%EC%9C%BC%EB%A1%9C-%EC%BC%9C%EC%A7%84-deployment-protection-%EB%81%84%EA%B8%B0\" aria-label=\"5단계 팀 기본값으로 켜진 deployment protection 끄기 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>5단계: 팀 기본값으로 켜진 Deployment Protection 끄기</h2>\n<p>배포는 Ready인데 임시 주소를 열면 <strong>302로 Vercel 로그인 페이지</strong>로 튕겼다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sS</span> <span class=\"token parameter variable\">-D</span> - <span class=\"token parameter variable\">-o</span> /dev/null https://blog-bluebutton.vercel.app/\n<span class=\"token comment\"># HTTP/2 302</span>\n<span class=\"token comment\"># location: https://vercel.com/sso-api?url=...</span></code></pre></div>\n<p>새 팀에 <strong>Vercel Authentication(Deployment Protection)</strong> 이 기본으로 켜져 있었다. 설정값은 <code class=\"language-text\">all_except_custom_domains</code>, 즉 <code class=\"language-text\">*.vercel.app</code> 주소는 로그인한 팀원만 볼 수 있고 커스텀 도메인은 공개된다는 뜻이다. 커스텀 도메인만 쓴다면 그대로 둬도 되지만, 공개 블로그는 임시 주소로도 점검해야 하므로 껐다. 대시보드의 Settings → Deployment Protection에서 끄거나, API로 바꿀 수 있다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-X</span> PATCH <span class=\"token string\">\"https://api.vercel.com/v9/projects/blog?teamId=team_xxx\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">-H</span> <span class=\"token string\">\"Authorization: Bearer <span class=\"token variable\">$VERCEL_TOKEN</span>\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">-H</span> <span class=\"token string\">\"Content-Type: application/json\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">-d</span> <span class=\"token string\">'{\"ssoProtection\": null}'</span></code></pre></div>\n<p>끄고 나서 임시 주소로 홈, 글 한 편, <code class=\"language-text\">sitemap.xml</code>, <code class=\"language-text\">rss.xml</code>, <code class=\"language-text\">robots.txt</code>, <code class=\"language-text\">ads.txt</code> 가 모두 200인지 확인했다. canonical과 사이트맵 URL은 코드 기본값 덕분에 처음부터 <code class=\"language-text\">www.bottlehs.dev</code> 로 나왔다.</p>\n<h2 id=\"6단계-도메인을-새-프로젝트에-추가하고-소유권-검증\" style=\"position:relative;\"><a href=\"#6%EB%8B%A8%EA%B3%84-%EB%8F%84%EB%A9%94%EC%9D%B8%EC%9D%84-%EC%83%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%86%8C%EC%9C%A0%EA%B6%8C-%EA%B2%80%EC%A6%9D\" aria-label=\"6단계 도메인을 새 프로젝트에 추가하고 소유권 검증 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>6단계: 도메인을 새 프로젝트에 추가하고 소유권 검증</h2>\n<p>두 번째로 막힌 지점이다. 도메인은 <strong>아직 정지된 팀의 프로젝트에 묶여 있다</strong>. 다른 팀이 같은 도메인을 추가하면 Vercel은 <code class=\"language-text\">_vercel</code> TXT 레코드로 소유권 검증을 요구한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">vercel domains <span class=\"token function\">add</span> www.bottlehs.dev blog <span class=\"token parameter variable\">--scope</span> bluebutton\nvercel domains <span class=\"token function\">add</span> bottlehs.dev blog <span class=\"token parameter variable\">--scope</span> bluebutton</code></pre></div>\n<p>API로 상태를 보면 <code class=\"language-text\">verified: false</code> 와 함께 넣어야 할 TXT 값이 나온다. 도메인마다 값이 다르고, 한 이름(<code class=\"language-text\">_vercel</code>)에 두 값을 함께 둘 수 있다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">이름: _vercel.bottlehs.dev   타입: TXT\n값:   vc-domain-verify=www.bottlehs.dev,xxxxxxxxxxxxxxxxxxxx\n값:   vc-domain-verify=bottlehs.dev,yyyyyyyyyyyyyyyyyyyy</code></pre></div>\n<h3 id=\"검증이-대기에서-멈추면-404가-난다\" style=\"position:relative;\"><a href=\"#%EA%B2%80%EC%A6%9D%EC%9D%B4-%EB%8C%80%EA%B8%B0%EC%97%90%EC%84%9C-%EB%A9%88%EC%B6%94%EB%A9%B4-404%EA%B0%80-%EB%82%9C%EB%8B%A4\" aria-label=\"검증이 대기에서 멈추면 404가 난다 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>검증이 “대기”에서 멈추면 404가 난다</h3>\n<p>TXT를 넣고 나흘 뒤에 사이트를 열어 보니 이번에는 <code class=\"language-text\">404 DEPLOYMENT_NOT_FOUND</code> 였다. DNS는 Vercel을 가리키는데, Vercel 입장에서는 그 호스트에 연결된 <strong>검증된</strong> 프로젝트가 없는 상태다. 확인해 보니 TXT 값은 정확히 들어가 있었지만 두 도메인 모두 <code class=\"language-text\">pending_domain_verification</code> 에 머물러 있었다. Vercel이 TXT를 알아서 재검사해 주지 않은 것이다.</p>\n<p>이때는 검증을 <strong>직접 트리거</strong>해야 한다. 대시보드의 도메인 항목에서 Refresh를 누르거나, API의 verify 엔드포인트를 호출한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-X</span> POST <span class=\"token string\">\"https://api.vercel.com/v9/projects/blog/domains/www.bottlehs.dev/verify?teamId=team_xxx\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">-H</span> <span class=\"token string\">\"Authorization: Bearer <span class=\"token variable\">$VERCEL_TOKEN</span>\"</span>\n<span class=\"token comment\"># {\"name\":\"www.bottlehs.dev\", ..., \"verified\":true}</span></code></pre></div>\n<p>호출 직후 <code class=\"language-text\">verified: true</code> 로 바뀌었고, 20초 안에 사이트가 200으로 돌아왔다. 대시보드에서 도메인을 다시 추가하면 검증 코드가 <strong>새로 발급</strong>되므로, DNS의 TXT 값은 항상 대시보드(또는 API)에 지금 표시되는 값과 맞춰야 한다.</p>\n<h2 id=\"7단계-dns-전환\" style=\"position:relative;\"><a href=\"#7%EB%8B%A8%EA%B3%84-dns-%EC%A0%84%ED%99%98\" aria-label=\"7단계 dns 전환 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>7단계: DNS 전환</h2>\n<p>Vercel은 도메인마다 권장 레코드를 알려 준다. 루트는 A 레코드, 서브도메인은 CNAME이다.</p>\n<table>\n<thead>\n<tr>\n<th>레코드</th>\n<th>이름</th>\n<th>값</th>\n<th>비고</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>A</td>\n<td><code class=\"language-text\">@</code></td>\n<td><code class=\"language-text\">216.150.1.1</code>, <code class=\"language-text\">216.150.16.1</code></td>\n<td>Vercel 공통 IP, 옛 값과 같으면 유지</td>\n</tr>\n<tr>\n<td>CNAME</td>\n<td><code class=\"language-text\">www</code></td>\n<td><code class=\"language-text\">xxxxxxxx.vercel-dns-0xx.com</code></td>\n<td>프로젝트별로 발급되는 값으로 교체</td>\n</tr>\n<tr>\n<td>TXT</td>\n<td><code class=\"language-text\">_vercel</code></td>\n<td><code class=\"language-text\">vc-domain-verify=...</code></td>\n<td>검증 후에도 삭제하지 않는다</td>\n</tr>\n</tbody>\n</table>\n<p>흥미로운 점은 <strong>www의 CNAME이 옛 프로젝트 값을 가리키는 동안에도 사이트가 열렸다</strong>는 것이다. <code class=\"language-text\">*.vercel-dns-*.com</code> 이 결국 Vercel 공통 IP로 풀리고, 라우팅은 호스트 이름 기준으로 검증된 프로젝트를 찾기 때문이다. 그래도 옛 레코드는 언제 정리될지 모르니 새 값으로 바꿔 두어야 한다. Cloudflare를 쓴다면 세 레코드 모두 프록시를 끄고 DNS only로 두는 편이 인증서 발급과 디버깅에 안전하다.</p>\n<h2 id=\"정리-이전-순서와-검증-명령\" style=\"position:relative;\"><a href=\"#%EC%A0%95%EB%A6%AC-%EC%9D%B4%EC%A0%84-%EC%88%9C%EC%84%9C%EC%99%80-%EA%B2%80%EC%A6%9D-%EB%AA%85%EB%A0%B9\" aria-label=\"정리 이전 순서와 검증 명령 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>정리: 이전 순서와 검증 명령</h2>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># 1. 로그인 전환</span>\nvercel <span class=\"token builtin class-name\">logout</span> <span class=\"token operator\">&amp;&amp;</span> vercel login <span class=\"token operator\">&amp;&amp;</span> vercel teams <span class=\"token function\">ls</span>\n\n<span class=\"token comment\"># 2. 새 프로젝트 연결</span>\n<span class=\"token function\">rm</span> <span class=\"token parameter variable\">-rf</span> .vercel <span class=\"token operator\">&amp;&amp;</span> vercel <span class=\"token function\">link</span> <span class=\"token parameter variable\">--scope</span> <span class=\"token operator\">&lt;</span>팀<span class=\"token operator\">></span> <span class=\"token parameter variable\">--project</span> <span class=\"token operator\">&lt;</span>이름<span class=\"token operator\">></span> <span class=\"token parameter variable\">--yes</span>\n\n<span class=\"token comment\"># 3. 환경 변수 (공개 접두사는 --no-sensitive)</span>\n<span class=\"token builtin class-name\">printf</span> <span class=\"token string\">'값'</span> <span class=\"token operator\">|</span> vercel <span class=\"token function\">env</span> <span class=\"token function\">add</span> KEY production <span class=\"token parameter variable\">--visibility</span> config --no-sensitive\n\n<span class=\"token comment\"># 4. 배포</span>\nvercel deploy <span class=\"token parameter variable\">--prod</span> <span class=\"token parameter variable\">--scope</span> <span class=\"token operator\">&lt;</span>팀<span class=\"token operator\">></span> <span class=\"token parameter variable\">--yes</span>\n\n<span class=\"token comment\"># 5. 접근 보호 확인 (302 → sso-api 면 끈다)</span>\n<span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sS</span> <span class=\"token parameter variable\">-D</span> - <span class=\"token parameter variable\">-o</span> /dev/null https://<span class=\"token operator\">&lt;</span>프로젝트<span class=\"token operator\">></span>.vercel.app/ <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">\"^HTTP\\|^location\"</span>\n\n<span class=\"token comment\"># 6. 도메인 추가 → TXT 등록 → 검증 트리거</span>\nvercel domains <span class=\"token function\">add</span> www.example.com <span class=\"token operator\">&lt;</span>프로젝트<span class=\"token operator\">></span> <span class=\"token parameter variable\">--scope</span> <span class=\"token operator\">&lt;</span>팀<span class=\"token operator\">></span>\n\n<span class=\"token comment\"># 7. 최종 확인</span>\n<span class=\"token keyword\">for</span> <span class=\"token for-or-select variable\">u</span> <span class=\"token keyword\">in</span> / /sitemap.xml /rss.xml /robots.txt<span class=\"token punctuation\">;</span> <span class=\"token keyword\">do</span>\n  <span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sS</span> <span class=\"token parameter variable\">-o</span> /dev/null <span class=\"token parameter variable\">-w</span> <span class=\"token string\">\"<span class=\"token variable\">$u</span> %{http_code}<span class=\"token entity\" title=\"\\n\">\\n</span>\"</span> https://www.example.com<span class=\"token variable\">$u</span>\n<span class=\"token keyword\">done</span></code></pre></div>\n<h2 id=\"재발-방지-호스팅-계정에-묶이지-않는-구조\" style=\"position:relative;\"><a href=\"#%EC%9E%AC%EB%B0%9C-%EB%B0%A9%EC%A7%80-%ED%98%B8%EC%8A%A4%ED%8C%85-%EA%B3%84%EC%A0%95%EC%97%90-%EB%AC%B6%EC%9D%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EA%B5%AC%EC%A1%B0\" aria-label=\"재발 방지 호스팅 계정에 묶이지 않는 구조 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>재발 방지: 호스팅 계정에 묶이지 않는 구조</h2>\n<p>도메인 만료와 계정 정지를 연달아 겪고 나니 결론은 하나다. <strong>배포 플랫폼의 특정 계정에만 존재하는 상태를 최소화</strong>해야 한다.</p>\n<ul>\n<li>설정은 코드에 둔다. 프레임워크, 빌드 명령, 리다이렉트, 헤더는 <code class=\"language-text\">vercel.json</code>, Node 버전은 <code class=\"language-text\">engines</code>, 사이트 주소는 코드 기본값으로.</li>\n<li>환경 변수는 “덮어쓰기”로만 쓰고, 어떤 키가 있는지 README나 글에 적어 둔다. 비밀값은 비밀 관리 도구에 사본을 둔다.</li>\n<li>모니터링 스크립트에 상태 코드뿐 아니라 <code class=\"language-text\">x-vercel-error</code> 헤더 검사를 넣는다. 402·403·404의 플랫폼 에러는 콘텐츠 404와 구분해야 한다.</li>\n<li>도메인 검증 TXT 레코드는 삭제하지 않는다. 다음 이전 때 다시 쓸 수 있다.</li>\n</ul>\n<p>지난 글의 <code class=\"language-text\">domain-check.sh</code> 에 다음 한 줄을 추가했다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token assign-left variable\">ERR</span><span class=\"token operator\">=</span><span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sS</span> <span class=\"token parameter variable\">-D</span> - <span class=\"token parameter variable\">-o</span> /dev/null <span class=\"token string\">\"<span class=\"token variable\">$URL</span>\"</span> <span class=\"token operator\">|</span> <span class=\"token function\">awk</span> -F<span class=\"token string\">': '</span> <span class=\"token string\">'tolower($1)==\"x-vercel-error\"{print $2}'</span> <span class=\"token operator\">|</span> <span class=\"token function\">tr</span> <span class=\"token parameter variable\">-d</span> <span class=\"token string\">'\\r'</span><span class=\"token variable\">)</span></span>\n<span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-n</span> <span class=\"token string\">\"<span class=\"token variable\">$ERR</span>\"</span> <span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">{</span> <span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"platform error: <span class=\"token variable\">$ERR</span>\"</span><span class=\"token punctuation\">;</span> <span class=\"token builtin class-name\">exit</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"faq\" style=\"position:relative;\"><a href=\"#faq\" aria-label=\"faq permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>FAQ</h2>\n<p><strong>Q: 정지된 계정의 프로젝트 설정이나 환경 변수를 꺼낼 방법은 없나요?</strong><br>\nA: 대시보드와 API, CLI 토큰이 모두 막히는 경우가 많아 사실상 없다. 코드에서 <code class=\"language-text\">process.env</code> 사용처를 찾아 목록을 복원하고, 값은 비밀 관리 도구나 문서에 남긴 사본에서 가져와야 한다. 사본이 없으면 발급처에서 재발급받는다.</p>\n<p><strong>Q: 다른 팀에 도메인을 추가했는데 404 DEPLOYMENT<em>NOT</em>FOUND가 납니다.</strong><br>\nA: 도메인이 아직 소유권 검증을 통과하지 못한 상태다. <code class=\"language-text\">_vercel</code> TXT 값이 대시보드에 지금 표시되는 값과 같은지 확인하고, 대시보드의 Refresh 또는 API의 verify 엔드포인트로 검증을 직접 트리거한다. TXT가 맞아도 자동 재검사가 오래 걸릴 수 있다.</p>\n<p><strong>Q: 배포는 Ready인데 vercel.app 주소가 Vercel 로그인 화면으로 넘어갑니다.</strong><br>\nA: 팀에 Deployment Protection이 기본으로 켜져 있어서다. 기본값 <code class=\"language-text\">all_except_custom_domains</code> 는 커스텀 도메인은 공개하고 vercel.app 주소만 보호한다. 공개 사이트라면 프로젝트 설정에서 끄거나 <code class=\"language-text\">ssoProtection</code> 을 <code class=\"language-text\">null</code> 로 바꾼다.</p>\n<p><strong>Q: GATSBY<em>·NEXT</em>PUBLIC_ 변수를 등록하려는데 secret으로 저장할 수 없다고 합니다.</strong><br>\nA: 브라우저 번들에 포함되는 공개 접두사 변수는 민감 정보로 저장할 수 없다. <code class=\"language-text\">--visibility config --no-sensitive</code> 로 일반 변수로 등록한다. 진짜 비밀값이라면 접두사를 빼고 서버에서만 읽도록 코드를 바꿔야 한다.</p>\n<p><strong>Q: DNS를 바꾸기 전에 새 프로젝트를 미리 점검할 수 있나요?</strong><br>\nA: 가능하다. 배포 후 <code class=\"language-text\">&lt;프로젝트>.vercel.app</code> 임시 주소로 홈, 글, 사이트맵, RSS, robots.txt를 확인한 뒤 도메인을 추가하면 된다. 접근 보호가 켜져 있으면 먼저 끄거나 <code class=\"language-text\">vercel curl</code> 로 우회해 점검한다.</p>\n<p><strong>Q: 옛 CNAME 값을 그대로 둬도 사이트가 열리는데 꼭 바꿔야 하나요?</strong><br>\nA: 바꿔야 한다. 프로젝트별 CNAME이 지금은 같은 공통 IP로 풀리지만 옛 레코드의 수명은 보장되지 않는다. Vercel이 새 프로젝트에 표시하는 값으로 교체하고, 루트 A 레코드는 공통 IP라 그대로 두면 된다.</p>","tableOfContents":"<ul>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#%EC%A6%9D%EC%83%81-402-%EC%9D%91%EB%8B%B5%EA%B3%BC-deployment_disabled\">증상: 402 응답과 DEPLOYMENT_DISABLED</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#%EC%98%AE%EA%B8%B0%EA%B8%B0-%EC%A0%84%EC%97%90-%EC%B1%99%EA%B8%B8-%EA%B2%83\">옮기기 전에 챙길 것</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#1%EB%8B%A8%EA%B3%84-cli-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%84-%EC%83%88-%ED%8C%80%EC%9C%BC%EB%A1%9C-%EB%B0%94%EA%BE%BC%EB%8B%A4\">1단계: CLI 로그인을 새 팀으로 바꾼다</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#2%EB%8B%A8%EA%B3%84-%EC%98%9B-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%81%ED%81%AC%EB%A5%BC-%EB%81%8A%EA%B3%A0-%EC%83%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%A7%8C%EB%93%A0%EB%8B%A4\">2단계: 옛 프로젝트 링크를 끊고 새 프로젝트를 만든다</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#3%EB%8B%A8%EA%B3%84-%ED%99%98%EA%B2%BD-%EB%B3%80%EC%88%98%EB%A5%BC-%EB%8B%A4%EC%8B%9C-%EB%93%B1%EB%A1%9D%ED%95%9C%EB%8B%A4\">3단계: 환경 변수를 다시 등록한다</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#4%EB%8B%A8%EA%B3%84-%ED%94%84%EB%A1%9C%EB%8D%95%EC%85%98-%EB%B0%B0%ED%8F%AC\">4단계: 프로덕션 배포</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#5%EB%8B%A8%EA%B3%84-%ED%8C%80-%EA%B8%B0%EB%B3%B8%EA%B0%92%EC%9C%BC%EB%A1%9C-%EC%BC%9C%EC%A7%84-deployment-protection-%EB%81%84%EA%B8%B0\">5단계: 팀 기본값으로 켜진 Deployment Protection 끄기</a></li>\n<li>\n<p><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#6%EB%8B%A8%EA%B3%84-%EB%8F%84%EB%A9%94%EC%9D%B8%EC%9D%84-%EC%83%88-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%86%8C%EC%9C%A0%EA%B6%8C-%EA%B2%80%EC%A6%9D\">6단계: 도메인을 새 프로젝트에 추가하고 소유권 검증</a></p>\n<ul>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#%EA%B2%80%EC%A6%9D%EC%9D%B4-%EB%8C%80%EA%B8%B0%EC%97%90%EC%84%9C-%EB%A9%88%EC%B6%94%EB%A9%B4-404%EA%B0%80-%EB%82%9C%EB%8B%A4\">검증이 “대기”에서 멈추면 404가 난다</a></li>\n</ul>\n</li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#7%EB%8B%A8%EA%B3%84-dns-%EC%A0%84%ED%99%98\">7단계: DNS 전환</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#%EC%A0%95%EB%A6%AC-%EC%9D%B4%EC%A0%84-%EC%88%9C%EC%84%9C%EC%99%80-%EA%B2%80%EC%A6%9D-%EB%AA%85%EB%A0%B9\">정리: 이전 순서와 검증 명령</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#%EC%9E%AC%EB%B0%9C-%EB%B0%A9%EC%A7%80-%ED%98%B8%EC%8A%A4%ED%8C%85-%EA%B3%84%EC%A0%95%EC%97%90-%EB%AC%B6%EC%9D%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EA%B5%AC%EC%A1%B0\">재발 방지: 호스팅 계정에 묶이지 않는 구조</a></li>\n<li><a href=\"/etc/Vercel-%EA%B3%84%EC%A0%95-%EC%A0%95%EC%A7%80%EB%A1%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EA%B0%80-%EB%82%B4%EB%A0%A4%EA%B0%94%EB%8B%A4-%EB%8B%A4%EB%A5%B8-%EA%B3%84%EC%A0%95%EC%9C%BC%EB%A1%9C-%EC%9E%AC%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B3%A0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%98%AE%EA%B8%B0%EA%B8%B0/#faq\">FAQ</a></li>\n</ul>","wordCount":{"words":1059},"fields":{"slug":"/etc/Vercel-계정-정지로-블로그가-내려갔다-다른-계정으로-재배포하고-도메인-옮기기/","image":null,"faq":[{"question":"정지된 계정의 프로젝트 설정이나 환경 변수를 꺼낼 방법은 없나요?","answer":"대시보드와 API, CLI 토큰이 모두 막히는 경우가 많아 사실상 없다. 코드에서 process.env 사용처를 찾아 목록을 복원하고, 값은 비밀 관리 도구나 문서에 남긴 사본에서 가져와야 한다. 사본이 없으면 발급처에서 재발급받는다."},{"question":"다른 팀에 도메인을 추가했는데 404 DEPLOYMENTNOTFOUND가 납니다.","answer":"도메인이 아직 소유권 검증을 통과하지 못한 상태다. vercel TXT 값이 대시보드에 지금 표시되는 값과 같은지 확인하고, 대시보드의 Refresh 또는 API의 verify 엔드포인트로 검증을 직접 트리거한다. TXT가 맞아도 자동 재검사가 오래 걸릴 수 있다."},{"question":"배포는 Ready인데 vercel.app 주소가 Vercel 로그인 화면으로 넘어갑니다.","answer":"팀에 Deployment Protection이 기본으로 켜져 있어서다. 기본값 allexceptcustomdomains 는 커스텀 도메인은 공개하고 vercel.app 주소만 보호한다. 공개 사이트라면 프로젝트 설정에서 끄거나 ssoProtection 을 null 로 바꾼다."},{"question":"GATSBY·NEXTPUBLIC 변수를 등록하려는데 secret으로 저장할 수 없다고 합니다.","answer":"브라우저 번들에 포함되는 공개 접두사 변수는 민감 정보로 저장할 수 없다. --visibility config --no-sensitive 로 일반 변수로 등록한다. 진짜 비밀값이라면 접두사를 빼고 서버에서만 읽도록 코드를 바꿔야 한다."},{"question":"DNS를 바꾸기 전에 새 프로젝트를 미리 점검할 수 있나요?","answer":"가능하다. 배포 후 <프로젝트>.vercel.app 임시 주소로 홈, 글, 사이트맵, RSS, robots.txt를 확인한 뒤 도메인을 추가하면 된다. 접근 보호가 켜져 있으면 먼저 끄거나 vercel curl 로 우회해 점검한다."},{"question":"옛 CNAME 값을 그대로 둬도 사이트가 열리는데 꼭 바꿔야 하나요?","answer":"바꿔야 한다. 프로젝트별 CNAME이 지금은 같은 공통 IP로 풀리지만 옛 레코드의 수명은 보장되지 않는다. Vercel이 새 프로젝트에 표시하는 값으로 교체하고, 루트 A 레코드는 공통 IP라 그대로 두면 된다."}]},"frontmatter":{"title":"Vercel 계정 정지로 블로그가 내려갔다 — 다른 계정으로 재배포하고 도메인 옮기기","date":"2026년 11월 7일","dateISO":"2026-11-07T01:00:00.000Z","updatedISO":null,"category":"etc","description":"배포 중이던 Vercel 계정이 정지되어 블로그가 402 DEPLOYMENT_DISABLED 응답만 내게 된 상황을, 코드 수정 없이 다른 Vercel 팀으로 옮겨 복구한 과정을 정리한다. 정지된 계정에서 미리 챙겨야 할 것, CLI로 새 팀에 프로젝트를 만들고 배포하는 순서, 팀 기본값으로 켜진 Deployment Protection, 도메인 소유권 검증이 멈춰 404가 나는 문제와 해결, DNS 전환 체크리스트까지 다룬다.","tags":["Vercel","배포","도메인","DNS","Gatsby","장애 대응","회고"]}}},"pageContext":{"slug":"/etc/Vercel-계정-정지로-블로그가-내려갔다-다른-계정으로-재배포하고-도메인-옮기기/","previous":{"fields":{"slug":"/javascript/Gatsby-블로그-GEO-AEO-적용기-JSON-LD-FAQPage-llms-txt-사이트맵/"},"frontmatter":{"title":"Gatsby 블로그 GEO·AEO 적용기 — JSON-LD, FAQPage 자동 생성, llms.txt, 사이트맵 정리","tags":["Gatsby","SEO","AI 검색","구조화 데이터","JavaScript","Vercel","웹 개발"]}},"next":null}},"staticQueryHashes":["213619243","3262363727"]}