문서·관리자 주소를 docs.barbelic.com·admin.barbelic.com으로 — 관리자 base /·문서 /admin 308 (2026-09-15)
- 기간: 2026-09-15 21:00 KST(오너 요청 "바벨릭 문서 주소를 docs.barbelic.com 으로 옮길 수 있을까, 관리자 페이지는 admin.barbelic.com 으로 옮기고") ~ 2026-09-15 (세션 1개
3cd8e0a8) · 이슈 #1666 - 랜딩: 문서 저장소 PR #127(Phase 1 코드, 병합
2920e3b4) · 이 기록 PR #131(Phase 3) · 앱 PR #1682(Phase 4, release/v0.19.4 큐 병합14171482) + 앱 Vercel Production 변수ADMIN_ALLOWED_ORIGINS· Vercel Production 게시: 관리자dpl_3VmSCFw4PKoTG8J6nKZNbW2cPTWp(docs maina1905bf, 그 뒤admin/변경 없음) · 문서barbelic-docs-beuytuv1z-dekerds-projects-4f9780ee.vercel.app(mainbe233ed). 마이그레이션·엣지 없음 - 설계서: 없음 — 이슈 #1666 본문(현재 상태 실측·Phase 계획·예상 효과·개선사항)
- 정본: 문서·관리자 독립 운영 §Vercel 프로젝트 설정·§기존 주소와 전환 검증 ·
admin/vite.config.mjs(base: "/") ·admin/vercel.json(옛/admin*→ 루트 308) ·scripts/write-docs-vercel-config.mjs(문서/admin*→BARBELIC_ADMIN_ORIGIN루트 308) ·admin/scripts/check-artifact.mjs(자산 경로/assets/) ·admin/src/react/services/adminConfig.ts(adminOAuthRedirect= 빌드 base) - 도구: 없음(Vercel CLI 59.11.7, 이 PC의 로그인으로 게시)
- 게이트:
check-artifact.mjs가/assets/경로를 요구하고/admin/assets/를 거부 · 단위admin/tests/adminBoundary.test.mjs(로그인 복귀 주소 = origin 루트) · 문서 저장소 CI docs·admin 범위(run 34969177863) - 버그리포트: 없음(관리자의 앱 API 주소가 옛 www에 남아 있던 문제는 이 기록 §2·§5에 적음)
- 계약: 없음
Phase 현황
| Phase | 내용 | 상태 |
|---|---|---|
| Phase 1 | 코드 — 관리자 base /, 옛 /admin* 308, 문서 /admin* → 관리자 origin 308, 산출물 검사·복귀 주소·테스트·설명 문장 | ✅ PR #127 (2920e3b4) |
| Phase 2 | 연결·설정·게시 — Vercel 도메인 2개, 관리자 API 주소, 앱 허용 origin, docs 저장소 변수, CLI 게시 | ✅ 코드 없음(이슈 댓글) |
| Phase 3 | 문서·기록 — 운영 문서·AGENTS.md 문구·이 기록·저장소 homepage | ✅ PR #131 |
| Phase 4 | 앱 v0.19.4 — deployment-targets.json adminOrigin, check:deployment 모양 검사, 배포 뒤 관리자 origin CORS 사전 요청 204 확인 단계 | ✅ 앱 PR #1682 (14171482, release/v0.19.4 큐 병합 — Production 반영은 v0.19.4 배포) |
1. 배경
2026-09-15 낮에 랜딩과 앱이 www.barbelic.com·app.barbelic.com으로 갈라졌지만(#1474·#1619), 문서 사이트와 관리자 페이지는 Vercel 기본 주소에 남아 있었다. 문서는 barbelic-docs.vercel.app, 관리자는 그 문서 사이트의 /admin/ 경로였고 실제 파일은 별도 프로젝트 barbelic-admin이 barbelic-admin.vercel.app/admin/으로 내보내는 것을 문서 사이트가 대신 전달했다(#1463 분리 때 옛 주소를 유지하려고 둔 구조). 오너가 두 주소를 docs.barbelic.com·admin.barbelic.com으로 옮길 수 있는지 물었다.
2. 문제 제기
문서·관리자의 공개 주소가 서비스 도메인이 아니었다
- 문서
https://barbelic-docs.vercel.app/, 관리자https://barbelic-docs.vercel.app/admin/(프로젝트는barbelic-admin).barbelic.com은 Vercel 등록 도메인이고 네임서버도 Vercel이며 하위 주소 전체(*)가 이미 Vercel을 가리켜서, 프로젝트에 붙이지 않은docs.·admin.은 http 404DEPLOYMENT_NOT_FOUND, https는 인증서가 없어 연결 실패였다.
관리자 빌드가 /admin/ 경로에 묶여 있었다
- Vite
base: "/admin/",admin/vercel.jsonrewrite 3개(/admin/·/admin/assets/*·/admin/*→ 산출물),check-artifact.mjs의 "/admin/assets/가 있어야 한다" 검사,adminConfig.ts의 로그인 복귀 주소/admin/고정. 문서 프로젝트도write-docs-vercel-config.mjs로/admin*을 관리자 origin의/admin*으로 rewrite했다. 관리자에 자기 도메인이 생기면 전부 불필요한 구조다.
관리자가 부르는 앱 API 주소가 옛 주소였다
- 배포된 관리자 도장이
appApiBaseUrl: "https://www.barbelic.com". #1619 뒤 www는 랜딩이라/api/admin/deployment-manifest가 308(끝 슬래시 추가)로 돌아오고, 관리자는 redirect를 오류로 처리(adminTransport.tsredirect: "error")해 운영 체크리스트의 "앱 배포 기대값(최신 마이그레이션·Edge 버전)" 조회가 실패했다. curl 실측GET … 308 → https://www.barbelic.com/api/admin/deployment-manifest/.
3. 해결 방안
원칙 (오너 결정 D1, 2026-09-15)
D1 "문서는 docs.barbelic.com, 관리자는 admin.barbelic.com으로 옮긴다" — 계획(이슈 #1666 본문) 승인 "오케이 고". 채택.
D2 (2026-09-15 밤) "이거 배포 19.4에 넣어줘" — 앱 허용 origin 적용을 지금 같은 코드로 재배포하지 않고 v0.19.4 배포에 싣는다. 채택(Phase 4).
접근
| 안 | 내용 | 결과 | 채택 |
|---|---|---|---|
| A | 관리자를 자기 origin의 루트(/)에서 열고, 옛 /admin* 경로는 308로 안내. 문서 사이트의 /admin*도 관리자 origin 루트로 308 | 배포 경로에 묶인 base·rewrite·검사·복귀 주소가 사라진다. 코드 변경은 문서 저장소(admin/·scripts/)만 | 채택 |
| B | 도메인만 붙이고 /admin/ base 유지(admin.barbelic.com/admin/) | 코드 변경 없음. 그러나 옛 결합 구조의 흔적(rewrite 3개·경로 고정)이 정본으로 굳는다 | 기각 |
| C | 문서 메뉴 "관리자" 링크에 새 주소를 코드로 새김 | staging 문서 사이트가 Production 관리자로 간다. 링크는 /admin/을 유지하고 환경 변수(BARBELIC_ADMIN_ORIGIN) 한 곳이 308 목적지를 정하는 편이 맞다 | 기각 |
| D | 옛 *.vercel.app 주소를 통째로 새 주소로 redirect | 앱 main(v0.19.2)의 /legal/* rewrite가 아직 barbelic-docs.vercel.app을 가리켜 v0.19.3 Production 뒤에야 가능 | 보류(범위 밖) |
| E | 앱 허용 origin 적용을 위해 지금 같은 코드로 Production 재배포 | 배포 한 번으로 바로 204. 오너 결정 D2로 v0.19.4 배포에 싣기로 | 기각(D2) |
| F | 앱에 adminOrigin을 원천으로 두고 배포 뒤 관리자 API CORS 사전 요청을 검사 | 허용 목록 변수는 코드 밖이라 어긋나도 아무도 모른다(관리자 API 주소가 www에 남은 것과 같은 유형). 배포 실행이 스스로 확인한다 | 채택(Phase 4) |
4. 적용한 내용
Phase 1 — 코드 (PR #127, 2920e3b4)
- 관리자:
admin/vite.config.mjsbase: "/".admin/vercel.jsonrewrite 3개 제거,/admin·/admin/·/admin/:path*→/·/:path*308(permanent), 헤더 규칙은 전체 경로.check-artifact.mjs는"/assets/가 있고/admin/assets/가 없어야 통과.adminOAuthRedirect는import.meta.env.BASE_URL(없으면/) 기준. e2eCASE-056·playwright.config.mjs의/admin/→/,adminBoundary.test.mjs갱신. - 문서:
scripts/write-docs-vercel-config.mjs가rewrites대신redirects(/admin*→${BARBELIC_ADMIN_ORIGIN}/…, 308)를 생성. 메뉴 "관리자" 링크는/admin/유지(주석 갱신). 루트 README·admin/README.md·운영 문서의 동작 설명 문장 갱신. - 검증:
npm run check:admin·BARBELIC_TARGET=local npm run build:admin· 단위 155/155 ·npm run check:docs(6 versions) ·npm run build:docs(381 routes) ·npm run check:docs-artifact(47 files) · 저장소 CI scope·docs·admin·verify 통과.
Phase 2 — 연결·설정·게시 (코드 없음)
- Vercel(팀
dekerds-projects-4f9780ee):docs.barbelic.com→barbelic-docs,admin.barbelic.com→barbelic-admin. 같은 팀 등록 도메인이라 DNS·검증 즉시, 인증서(Let's Encrypt) 자동. barbelic-adminProduction 변수VITE_APP_API_BASE_URL=https://app.barbelic.com(전https://www.barbelic.com).- 앱
barbelicProduction 변수ADMIN_ALLOWED_ORIGINS=https://barbelic-docs.vercel.app,https://barbelic-docs-dekerds-projects-4f9780ee.vercel.app,https://barbelic-admin.vercel.app,https://admin.barbelic.com(읽을 수 있는 config 형식, 되읽어 확인). 앱 Production 새 배포부터 적용. - docs 저장소 GitHub
production환경 변수BARBELIC_ADMIN_ORIGIN=https://admin.barbelic.com(전https://barbelic-admin.vercel.app). - 오너: Supabase Production → Authentication → URL Configuration → Redirect URLs에
https://admin.barbelic.com/**추가(옛 항목 유지). - CLI 게시(저장소 루트, 워크플로와 같은 순서): 관리자
vercel link → pull --environment=production → build --prod → deploy --prebuilt --prod(--local-config admin/vercel.json) →dpl_3VmSCFw4PKoTG8J6nKZNbW2cPTWp,admin.barbelic.com에 별칭. 문서BARBELIC_ADMIN_ORIGIN=https://admin.barbelic.com node scripts/write-docs-vercel-config.mjs→ 같은 순서(--local-config .vercel-docs.generated.json) →barbelic-docs-beuytuv1z-…(mainbe233ed).
Phase 3 — 문서·기록 (PR #131)
- 운영 문서 상태 표·Vercel 프로젝트 설정·
BARBELIC_ADMIN_ORIGIN값·전환 기록 절,AGENTS.md배포 문구, 이 기록과 등록 2곳, 저장소 homepagehttps://docs.barbelic.com.
Phase 4 — 앱 v0.19.4 배포 검사 (PR #1682, release/v0.19.4 큐 병합 14171482)
deployment-targets.json: 환경별adminOrigin(productionhttps://admin.barbelic.com, staginghttps://barbelic-admin-env-staging-dekerds-projects-4f9780ee.vercel.app) +$comment설명. 주소 원천은 이 파일 한 곳(#1474 원칙), 워크플로에 리터럴 없음.scripts/check-deployment-pipeline.mjs(npm run check):adminOrigin이 https origin이고publicOrigin과 다른지 검사..github/workflows/deploy-steps.ymlfrontend 잡: 공개 주소·옛 주소 검사 뒤 "관리자 origin에서 보낸 OPTIONS/api/admin/deployment-manifest가 204인가"를 최대 6회(10초 간격) 확인. 403이면 배포 실행이 빨간불(배포 자체는 완료된 뒤의 확인 단계).- 검증:
npm run check통과 · 단계 본문bash -n· 같은 요청 실측 staging 204 / production 403(변수 변경 전 배포 — v0.19.4 배포부터 204 기대) · Merge Check run 34981022762 통과. precheck 생략(오너 지시 2026-09-15, Merge Check만).
주요 결정과 그 근거
- 관리자는 루트에서 연다(A):
admin.barbelic.com/admin/은 주소가 두 번 말하는 셈이고,/admin/base는 문서 도메인 아래 얹혀 살던 시절의 산물이다. 옛 북마크는 308로 받는다. - 문서 메뉴 링크는
/admin/유지(C 기각): 목적지는 환경 변수 한 곳이 정한다. staging 문서 사이트는 staging 관리자로, Production은admin.barbelic.com으로 간다. - 문서 사이트의
/admin*은 rewrite가 아니라 redirect: 문서 프로젝트가 관리자 산출물을 대신 내보내는 책임을 버린다. 관리자 자산 요청이 문서 도메인으로 오는 일이 없어진다. - vercel.app 주소는 그대로(D 보류): 앱 main의
/legal/*rewrite가 아직 그 주소를 쓴다. - 허용 origin 적용은 v0.19.4 배포로(D2), 그 배포가 스스로 확인(F): v0.19.3 Production 배포(22:14 KST)가 변수 변경(22:19 KST~)보다 먼저 나가 새 주소가 403인 채였다. 재배포 대신 v0.19.4에 싣되, 변수가 코드 밖에 있어 생기는 "어긋나도 모르는" 상태를 배포 실행의 검사 단계로 막는다.
작업 중 드러난 것
- 앱 Vercel 프로젝트는 Production 변수를 기본으로 비밀(Secret) 형식으로 저장한다. 처음 넣은
ADMIN_ALLOWED_ORIGINS를 되읽을 수 없어 지우고vercel env add … --type config로 다시 넣어 값을 확인했다. 되읽어야 하는 값은 처음부터--type config. - 게시 도중 docs main이 다른 세션의 기록 PR(#128·#130·#129)로 전진했다. Docs Deploy 워크플로의 "branch 최신 = 게시" 원칙대로 문서를 최신 main(
be233ed)으로 한 번 더 게시했다.admin/은 그 사이 변경이 없어 관리자는 재게시하지 않았다. - Supabase 로그인 복귀 허용 목록은 밖에서 확인할 수 없다(authorize의
state가 불투명 값). 오너 추가 완료를 전제로 게시했고, 로그인 시작 302는 카카오·Google·Apple 모두 확인했다. vercel build가 문서 산출물에서archive\error-cases\*.htmloverride 경로 경고 3건을 낸다(Windows 경로 구분자, 이전 게시와 같은 경고). 게시 결과에 영향 없음.
5. 적용 결과
| 항목 | 전 → 후 |
|---|---|
| 문서 공개 주소 | barbelic-docs.vercel.app → https://docs.barbelic.com/ 200(문서 페이지·/legal/terms-v4·/account/delete 200). 옛 주소 200 유지(별칭) |
| 관리자 공개 주소 | barbelic-docs.vercel.app/admin/(프록시) → https://admin.barbelic.com/ 200, 도장 appApiBaseUrl=https://app.barbelic.com, 자산 /assets/* 200, nosniff·referrer 헤더 |
| 옛 관리자 경로 | /admin/ 200(옛 파일) → admin.barbelic.com/admin·/admin/·/admin/assets/x.js 308 → 루트 경로 · barbelic-admin.vercel.app/admin/ 308 → / · docs.barbelic.com/admin·/admin/x/y·barbelic-docs.vercel.app/admin/ 308 → https://admin.barbelic.com/…(경로 유지) |
| 관리자 → 앱 API 주소 | www.barbelic.com(랜딩, 308로 실패) → app.barbelic.com(무인증 401 = 정상 응답 경로) |
| 로그인 시작 | 복귀 주소 https://admin.barbelic.com/로 카카오·Google·Apple 각 302 |
| 앱 API 허용 origin | 변수에 admin.barbelic.com 추가(되읽어 확인). 적용은 앱 v0.19.4 Production 배포부터이며(v0.19.3 배포가 변수 변경 5분 전에 나감), 그 배포 실행의 "The admin origin must be allowed by the admin API" 단계가 204를 자동 확인한다(Phase 4). 옛 origin 204 유지 |
| Supabase 복귀 허용 목록 | 오너가 대시보드에서 추가. 미검증(밖에서 확인 불가) |
| 관리자 코드의 경로 고정 | base /admin/·rewrite 3개·검사 특례·복귀 주소 고정 → 0 |
| 문서 프로젝트의 관리자 대리 전달 | rewrite 3개 → redirect 3개 |
| 인증서 | 없음(연결 실패) → Let's Encrypt 자동 발급, 두 주소 모두 https 정상 |
6. 이번 개선으로 향상된 것
주소 하나로 관리자에 간다
오너는 admin.barbelic.com만 기억하면 된다. 문서 사이트의 옛 /admin 링크와 북마크는 308로 같은 곳에 닿는다.
관리자 빌드가 어디에 놓이든 같다
base와 복귀 주소가 배포 경로에 묶이지 않아, 앞으로 주소나 프로젝트를 옮겨도 admin/을 고칠 일이 없다. 산출물 검사가 루트 자산 경로를 지킨다.
관리자 운영 체크리스트가 앱과 다시 통한다
앱 API 주소가 앱 정규 주소와 같아졌다. 앱 v0.19.4 Production 배포부터 새 관리자 주소의 CORS도 열리고, 그 배포 실행이 허용 여부를 스스로 확인한다(Phase 4).
구조적으로 남는 것: 문서·관리자가 각자 도메인을 가진 독립 프로젝트(문서 프로젝트는 관리자 산출물을 대신 내보내지 않는다), BARBELIC_ADMIN_ORIGIN 한 곳이 문서 사이트의 /admin 목적지를 정한다, check-artifact.mjs의 루트 자산 경로 게이트.
남은 것
- 도메인 정본(문서 PR #84
docs/platform/domains.md, 미병합)에 docs·admin 행 추가 — 그 PR 담당. - 옛
*.vercel.app주소의 전체 redirect(D)는 앱 main의/legal/*rewrite 제거(v0.19.3) 뒤. - Docs/Admin Deploy 자동 실행(
VERCEL_TOKEN)은 #1463 잔여 그대로 — 그때까지 게시는 CLI.