트러블슈팅
이 페이지는 사람들이 가장 자주 멈추는 자리를 모아 둔 곳입니다. 본인이 보고 있는 증상과 가까운 항목을 찾아 그 아래의 안내를 따라가 보세요. 이 페이지에 없는 증상이라면 에러 메시지를 그대로 복사해서 Claude Code 에 붙여 넣고 “이거 어떻게 고쳐?” 라고 물으면 다음에 시도할 만한 한 수가 보통 따라옵니다.
환경 설정에서 막힐 때
섹션 제목: “환경 설정에서 막힐 때”Node 가 설치되지 않습니다
섹션 제목: “Node 가 설치되지 않습니다”대개 nvm install 20 이 도중에 멎거나 그냥 실패한 상태입니다.
macOS 와 Linux 에서는 새 터미널을 열고 command -v nvm 을 실행해 봅니다. 출력이 비어 있다면 nvm 자체는 설치됐지만 셸 시작 파일(.zshrc 또는 .bashrc)에 로더가 안 들어간 상태입니다. nvm 설치 출력 끝부분에 적혀 있던 두 줄(export NVM_DIR="$HOME/.nvm" ...)을 그 파일 안에 손으로 붙여 넣고 새 터미널을 엽니다.
Windows 에서는 WSL2 설치를 끝까지 마쳤는지 다시 한번 확인합니다. 이 가이드의 명령은 PowerShell 에서 동작하지 않습니다. 모든 단계는 WSL2 위 Ubuntu 셸 안에서 실행해야 합니다.
node --version 이 v20 보다 낮은 숫자를 출력합니다
섹션 제목: “node --version 이 v20 보다 낮은 숫자를 출력합니다”여러 Node 버전이 깔려 있고 시스템 기본이 옛 버전을 가리키는 상태입니다.
nvm use 20nvm alias default 20이 두 줄을 실행한 다음 새 터미널을 열고 node --version 을 다시 확인합니다.
pnpm install 이 권한 에러로 실패합니다
섹션 제목: “pnpm install 이 권한 에러로 실패합니다”EACCES 또는 permission denied 가 보인다면 npm 글로벌 설치 위치 권한이 가장 흔한 원인입니다. 다음을 순서대로 시도해 봅니다.
sudo로 다시 시도하지 마세요. 보통 문제를 더 키웁니다.- 이전 시도에서 만들어진
node_modules/가 있다면 지우고 다시:rm -rf node_modules pnpm-lock.yaml. - 그래도 안 풀리면 nvm 으로 깐 Node 를 다시 설치:
nvm uninstall 20 && nvm install 20.
Docker 가 안 떠 있어 supabase start 가 실패합니다
섹션 제목: “Docker 가 안 떠 있어 supabase start 가 실패합니다”Cannot connect to the Docker daemon 또는 비슷한 메시지가 보입니다. macOS 와 Windows 는 Docker Desktop 이 실행 중인지 확인합니다. 시스템 트레이의 고래 아이콘이 회색이 아니라 동작 중 상태여야 합니다.
Linux 에서는 docker ps 가 권한 에러로 막히는 경우가 있습니다. 01-prerequisites.md 의 usermod -aG docker $USER 자리를 실행한 다음 한 번 로그아웃하고 다시 들어왔는지 확인하세요.
env 변수에서 막힐 때
섹션 제목: “env 변수에서 막힐 때”Missing environment variable VITE_SUPABASE_URL 같은 빌드 에러
섹션 제목: “Missing environment variable VITE_SUPABASE_URL 같은 빌드 에러”src/shared/config/env.ts 의 zod 검증이 잡은 자리입니다. 다음 셋 중 하나입니다.
.env.local파일 자체가 없는 상태 —cp .env.example .env.local부터- 파일은 있는데
VITE_SUPABASE_URL=줄이 비어 있는 상태 — Supabase 대시보드의 Settings → API 에서 다시 복사 - prefix 가
VITE_가 아닌 상태 (예:SUPABASE_URL=...만 박혀 있음) —VITE_를 앞에 붙여야 클라이언트 번들에 노출됨
env 변수를 고친 다음에는 pnpm dev 를 한 번 끄고 다시 띄워야 반영됩니다. Vite 는 dev 서버 부팅 시점에 .env.local 을 한 번만 읽습니다.
STRIPE_SECRET_KEY 가 클라이언트 콘솔에 undefined 로 찍힙니다
섹션 제목: “STRIPE_SECRET_KEY 가 클라이언트 콘솔에 undefined 로 찍힙니다”이 키는 VITE_ prefix 가 없어서 클라이언트에 노출되지 않는 자리입니다. 정상입니다. Stripe Secret key 는 Edge Function 안에서 Deno.env.get('STRIPE_SECRET_KEY') 로 읽고, 그 값은 supabase secrets set 으로 박혀 있어야 합니다.
supabase secrets list목록에 STRIPE_SECRET_KEY 가 안 보인다면 그 자리부터 박습니다.
supabase secrets set STRIPE_SECRET_KEY=sk_test_...Supabase 연결에서 막힐 때
섹션 제목: “Supabase 연결에서 막힐 때”회원가입이 안 됩니다
섹션 제목: “회원가입이 안 됩니다”먼저 .env.local 의 VITE_SUPABASE_URL 과 VITE_SUPABASE_ANON_KEY 가 잘못 박혀 있는지 확인합니다. URL 은 https://<ref>.supabase.co 형태이고 끝에 / 가 붙으면 안 됩니다.
값이 맞다면 Supabase 대시보드의 Authentication → Providers 로 가서 Email 자리가 활성화돼 있는지 확인합니다. 가입을 받지 않는 상태로 잠겨 있는 경우가 있습니다.
브라우저 DevTools 의 Network 탭을 열고 가입 버튼을 누른 다음 supabase.co 로 가는 요청의 응답 본문을 읽어 봅니다. 거절 사유가 거기 적혀 있습니다.
Supabase 에 데이터가 들어오지 않습니다
섹션 제목: “Supabase 에 데이터가 들어오지 않습니다”Table Editor 를 열고 본인 도메인 테이블이 실제로 존재하는지 먼저 확인합니다. SQL 마이그레이션이 적용 안 된 상태일 수 있습니다.
supabase db push테이블이 있는데 데이터가 안 들어온다면 RLS 정책 자리입니다. 기본은 default deny 라 정책이 없으면 INSERT 도 막힙니다. Authentication → Policies 로 가서 그 테이블의 정책 목록을 봅니다. 정책이 비어 있다면 api/migrations/ 안의 SQL 자리에서 정책을 추가하고 supabase db push 를 다시 돌립니다.
UI 에서 직접 정책을 만들지 마세요. UI 에서 만든 정책은 git 에 박히지 않아 다음 환경에서 사라지는 자리가 됩니다.
401 또는 403 에러
섹션 제목: “401 또는 403 에러”anon 키를 다시 복사합니다. 붙여 넣을 때 끝에 공백이나 줄바꿈이 따라 들어가는 경우가 흔한 원인입니다. service_role 키는 절대 클라이언트 안에서 쓰지 마세요. 이 키는 RLS 를 우회하므로 클라이언트에 박히면 모든 행이 노출됩니다.
Stripe 결제에서 막힐 때
섹션 제목: “Stripe 결제에서 막힐 때”Stripe webhook 서명 검증이 실패합니다
섹션 제목: “Stripe webhook 서명 검증이 실패합니다”Webhook signature verification failed 가 Edge Function 로그에 보입니다. 거의 항상 다음 셋 중 하나입니다.
STRIPE_WEBHOOK_SECRET이supabase secrets에 안 박혀 있는 상태.supabase secrets list로 확인하고 빠져 있으면supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_...으로 박습니다.- secret 이 박혀 있는데 값이 다른 endpoint 의 것. Stripe 대시보드의 Developers → Webhooks 에서 본인 endpoint 를 누르면 Signing secret 자리가 보입니다. 그 값을 다시 복사합니다.
- 로컬 개발에서 Stripe CLI 의
stripe listen으로 forwarded 한 자리.stripe listen이 출력하는 webhook signing secret (whsec_...) 은 대시보드의 것과 다릅니다. 로컬에서는 그 값으로 박아야 검증이 통과합니다.
Checkout 화면이 떴다 닫혔다 합니다
섹션 제목: “Checkout 화면이 떴다 닫혔다 합니다”pricing-grid 의 Price ID 가 placeholder 인 상태에서 결제 버튼을 누른 경우입니다. src/widgets/pricing-grid/model/plans.ts 의 Price ID 자리에 본인 Stripe 대시보드의 test mode Price ID 가 박혀 있어야 합니다.
본인 Price ID 는 Stripe 대시보드의 Products 에서 Pro 또는 Enterprise 제품을 누르면 그 안 가격 자리에 price_... 형태로 박혀 있습니다.
FSD lint 가 빌드를 차단합니다
섹션 제목: “FSD lint 가 빌드를 차단합니다”Cross-feature import not allowed
섹션 제목: “Cross-feature import not allowed”features/checkout 안에서 features/sign-in 을 import 한 자리. FSD 6 레이어 규칙으로 같은 레이어 안 슬라이스 간 직접 import 는 금지입니다.
두 feature 가 공유하는 로직이 있다면 그 자리를 shared/lib/ 또는 entities/ 로 끌어내립니다. 또는 두 feature 를 한 단계 위 widget 자리에서 합성합니다 (예: widgets/auth-checkout-flow/).
cannot import from internal path
섹션 제목: “cannot import from internal path”features/checkout/model/useCheckout.ts 를 다른 슬라이스에서 직접 import 한 자리. FSD 규칙은 슬라이스 바깥에서는 index.ts (public API) 만 import 할 수 있다고 잡습니다.
// 금지import { useCheckout } from '@/features/checkout/model/useCheckout';
// 허용 — index.ts 가 export 한 것만import { useCheckout } from '@/features/checkout';jsx-a11y/alt-text lint 에러
섹션 제목: “jsx-a11y/alt-text lint 에러”<img> 에 alt 속성이 없는 자리. 장식용 이미지라면 빈 문자열로 두면 됩니다.
// 의미 있는 이미지<img src="/logo.svg" alt="MyApp 로고" />
// 장식용 이미지 (스크린리더가 무시)<img src="/decoration.svg" alt="" />빌드와 dev 서버에서 막힐 때
섹션 제목: “빌드와 dev 서버에서 막힐 때”5173 포트가 이미 사용 중입니다
섹션 제목: “5173 포트가 이미 사용 중입니다”Port 5173 is in use, trying another one... 메시지가 떨어집니다. 이전에 띄워 둔 dev 서버가 종료되지 않은 경우입니다.
lsof -ti:5173 | xargs kill위 명령으로 그 포트를 잡고 있는 프로세스를 종료한 다음 다시 pnpm dev 를 실행합니다. Vite 가 자동으로 5174 같은 다른 포트를 잡아주기도 하므로 그쪽 URL 로 진입해도 됩니다.
코드를 수정했는데 화면에 반영이 안 됩니다
섹션 제목: “코드를 수정했는데 화면에 반영이 안 됩니다”대개 dev 서버가 멎어 있는 상태입니다. 터미널을 보고 pnpm dev 가 살아 있는지 확인합니다. 살아 있는데 반영이 안 된다면 브라우저 캐시이니 강제 새로고침 (Cmd+Shift+R 또는 Ctrl+Shift+R) 합니다.
tokens.css 같은 CSS 자리 수정은 가끔 HMR 이 못 잡는 경우가 있습니다. dev 서버를 한 번 끄고 다시 띄우면 깔끔합니다.
pnpm build 가 type error 로 실패합니다
섹션 제목: “pnpm build 가 type error 로 실패합니다”src/features/checkout/model/useCheckout.ts(14,7): error TS2322: Type 'string' is not assignable to type 'PriceId'.이 모양의 에러는 AI 가 짠 코드에서 타입이 어긋난 자리입니다. 에러 출력을 그대로 Claude Code 에 붙여 넣고 “이거 고쳐 줘” 라고 입력하면 AI 가 그 자리를 잡아 줍니다.
빌드가 깨진 상태로 commit 을 시도하면 pre-commit-check.sh 훅이 차단합니다. 정상입니다. 그 훅이 본인 git 히스토리에 깨진 코드가 박히는 자리를 막아 줍니다.
그 밖에
섹션 제목: “그 밖에”이 페이지에 같은 증상이 없다면 두 가지를 더 시도해 볼 수 있습니다.
먼저, 에러 메시지 전체를 복사해 Claude Code 에 붙여 넣고 “이거 고쳐 줘” 라고 입력합니다. 다음에 시도할 한 수를 보통 잘 짚어 줍니다.
그래도 풀리지 않는다면 GitHub 이슈를 열거나 팀 Slack 에 글을 올립니다. 다음 세 가지를 함께 적어 주세요.
- 어디서 막혔는지 (어느 파일, 어느 명령)
- 에러 메시지 전체
- 환경 정보 (macOS / Linux / Windows, Node 버전, Docker 버전, Supabase CLI 버전)