바이브코딩 · 검수된 답변

바이브코딩으로 웹 하나를 실제 배포하고 DB/API까지 연결하는 과정

바이브코딩으로 만든 웹을 실제 서비스로 만들려면 GitHub, Render 배포, Supabase PostgreSQL, DATABASE_URL, API Key, 도메인, DB 연결 검증까지 이어서 확인해야 합니다.

바이브코딩으로 웹 하나를 실제 배포하고 DB/API까지 연결하는 과정

바이브코딩으로 웹을 만든다고 하면 보통 “화면이 예쁘게 뜨는 MVP”까지는 금방 갑니다. 하지만 실제 서비스로 쓰려면 그 다음 단계가 더 중요합니다.

핵심은 이겁니다.

코드 생성
↓
GitHub에 저장
↓
PostgreSQL DB 연결
↓
API Key와 Secret을 환경변수로 분리
↓
배포 서비스에 올림
↓
도메인 연결
↓
실제 URL에서 DB/API/페이지가 작동하는지 확인

아래는 Next.js, Prisma, Supabase PostgreSQL, Render, Cloudflare DNS를 기준으로 웹 하나를 실제로 작동시키는 전체 과정입니다.


1. Render에서 프로젝트 상태 확인

먼저 배포 플랫폼에서 내 서비스가 살아 있는지 확인합니다. 여기서는 Render를 사용했습니다.

Render 프로젝트 대시보드

Render 대시보드에서 프로젝트 카드에 All services are up and running이 보이면 연결된 서비스가 정상 실행 중이라는 뜻입니다.

이 화면에서 확인할 것:

바이브코딩으로 만든 웹도 결국 서버 위에서 돌아가야 합니다. 로컬에서만 보이는 화면은 아직 서비스가 아닙니다. Render, Vercel, Railway, Fly.io 같은 곳에 올라가야 실제 도메인으로 접속할 수 있습니다.


2. Web Service 상세 화면에서 배포 상태 확인

프로젝트를 클릭하면 실제 Web Service 상세 화면으로 들어갈 수 있습니다.

Render Web Service 상세 화면

이 화면에서는 다음을 확인합니다.

Deploy live가 보이면 해당 커밋이 실제 서비스에 반영된 상태입니다.

Render 무료 인스턴스는 일정 시간 접속이 없으면 잠들 수 있습니다. 그래서 첫 접속이 30~60초 정도 느릴 수 있습니다. 이건 오류라기보다 무료 플랜의 동작 방식입니다.


3. API Key와 DB 주소는 코드가 아니라 Environment Variables에 넣기

API Key, DB 비밀번호, 인증 Secret은 코드에 직접 넣으면 안 됩니다.

좋은 방식은 배포 플랫폼의 환경변수에 저장하고, 코드에서는 변수 이름으로만 읽는 것입니다.

Render Environment Variables

예를 들어 Render의 Environment Variables에는 이런 값들이 들어갑니다.

DATABASE_URL=********
OPENAI_API_KEY=********
OPENAI_MODEL=gpt-5-mini
AUTH_SECRET=********
NEXT_PUBLIC_SITE_URL=https://example.com

코드에서는 이렇게 읽습니다.

const databaseUrl = process.env.DATABASE_URL;
const openaiKey = process.env.OPENAI_API_KEY;

절대 이렇게 쓰면 안 됩니다.

const openaiKey = "sk-...";
const databaseUrl = "postgresql://user:password@host:5432/db";

비밀값을 코드에 넣으면 GitHub에 올라갈 수 있고, 한 번 노출된 키는 폐기하고 새로 만들어야 합니다.


4. Supabase에서 PostgreSQL DATABASE_URL 가져오기

DB는 Supabase PostgreSQL을 사용했습니다. Supabase 프로젝트에서 Connect to your project를 열고 Direct → Connection string을 선택하면 PostgreSQL URI를 확인할 수 있습니다.

Supabase Direct Connection String

형태는 보통 이렇게 생겼습니다.

postgresql://postgres:[YOUR-PASSWORD]@db.xxxxx.supabase.co:5432/postgres

각 부분의 의미는 다음과 같습니다.

실제 DATABASE_URL에는 [YOUR-PASSWORD] 부분을 내가 만든 DB 비밀번호로 바꿔 넣습니다.

단, 이 값은 절대 블로그, README, 코드, 스크린샷에 그대로 노출하면 안 됩니다.


5. 로컬에서 환경변수를 안전하게 넣는 방법

Windows PowerShell에서 .env에 값을 넣을 때 한 줄에 키를 직접 쓰면 터미널 기록에 남을 수 있습니다. 조금 더 안전하게 하려면 입력값을 숨기는 방식으로 넣습니다.

예를 들어 DATABASE_URL을 넣을 때:

$secret = Read-Host "DATABASE_URL 입력" -AsSecureString
$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
  [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret)
)
Add-Content -Path ".env" -Value "DATABASE_URL=$plain"
Remove-Variable plain
Remove-Variable secret

OpenAI API Key도 같은 방식으로 넣을 수 있습니다.

$secret = Read-Host "OPENAI_API_KEY 입력" -AsSecureString
$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
  [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret)
)
Add-Content -Path ".env" -Value "OPENAI_API_KEY=$plain"
Remove-Variable plain
Remove-Variable secret

그리고 .env는 반드시 .gitignore에 포함되어야 합니다.

확인 명령:

git status --short

여기서 .env가 나오면 안 됩니다.


6. Prisma로 DB 연결 확인하기

DATABASE_URL을 넣었다면 Prisma가 실제 PostgreSQL에 연결되는지 확인해야 합니다.

개발 중 자주 쓰는 명령은 이 순서입니다.

npm.cmd run db:generate
npm.cmd run db:migrate
npm.cmd run db:seed
npm.cmd run db:check

운영 배포에서는 migrate dev가 아니라 migrate deploy를 사용합니다.

npm.cmd run db:deploy

실제 DB 연결 확인 결과는 아래처럼 볼 수 있습니다.

터미널 DB 연결 확인

이 결과가 나오면 애플리케이션이 Supabase PostgreSQL에 실제로 연결되고 있다는 뜻입니다.

PostgreSQL OK: select=1, categories=3, seedTopics=14, keywords=14, questions=15

여기서 중요한 점은 mock DB나 메모리 DB가 아니라 실제 PostgreSQL을 보고 있어야 한다는 것입니다.


7. 배포 명령과 운영 명령 구분하기

로컬 개발에서 쓰는 명령과 운영 배포에서 쓰는 명령은 다릅니다.

개발용:

npm.cmd run dev

개발 DB migration:

npm.cmd run db:migrate

운영 DB migration:

npm.cmd run db:deploy

운영 배포 전 검증:

npm.cmd run lint
npm.cmd run typecheck
npm.cmd test
npm.cmd run build

Render의 Build Command에는 보통 이런 식으로 들어갑니다.

npm install && npm run build && npm run db:deploy

Start Command는 프로젝트에 맞춰 설정합니다.

npm run start

8. 도메인 연결

배포가 끝나면 Render가 기본 URL을 줍니다. 하지만 실제 서비스처럼 보이려면 커스텀 도메인을 연결하는 것이 좋습니다.

보통 흐름은 이렇습니다.

Render에서 Custom Domain 추가
↓
Render가 DNS target 제공
↓
Cloudflare DNS로 이동
↓
A, CNAME, 또는 CNAME flattening 설정
↓
SSL 발급 대기
↓
https://내도메인 접속 확인

예:

infofixhub.org
www.infofixhub.org

DNS 확인:

nslookup infofixhub.org
nslookup www.infofixhub.org

웹 응답 확인:

Invoke-WebRequest -Uri "https://infofixhub.org" -UseBasicParsing

9. API Key가 없어도 기본 앱은 죽지 않게 만들기

OpenAI 같은 API는 optional provider로 두는 게 좋습니다.

즉, API Key가 없으면 AI 생성 기능만 비활성화되고, 기본 페이지와 DB 기능은 살아 있어야 합니다.

좋은 처리:

if (!process.env.OPENAI_API_KEY) {
  throw new Error("OpenAI provider is not connected");
}

더 좋은 운영 처리:

if (!process.env.OPENAI_API_KEY) {
  return {
    enabled: false,
    reason: "not_configured",
  };
}

나쁜 처리:

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY!,
});

이렇게 하면 환경변수가 없을 때 앱 전체가 죽을 수 있습니다.


10. 실제 작동 확인 체크리스트

배포 후에는 “열린다”만 확인하면 부족합니다. 아래를 순서대로 확인해야 합니다.

10.1 페이지 확인

Invoke-WebRequest -Uri "https://infofixhub.org" -UseBasicParsing

확인할 것:

10.2 DB Health 확인

Invoke-WebRequest -Uri "https://infofixhub.org/api/health/db" -UseBasicParsing

응답에는 DB 비밀번호나 connection string이 나오면 안 됩니다.

좋은 응답:

{
  "ok": true
}

10.3 DB 데이터 확인

npm.cmd run db:check

10.4 CRUD 확인

관리자 화면에서 데이터를 생성합니다.

Admin
↓
SeedTopic / Keyword / Question 생성
↓
DB 저장 확인
↓
공개 페이지 확인

10.5 CTA/Redirect 확인

광고나 CTA가 있다면 실제 redirect도 확인해야 합니다.

try {
  $r = Invoke-WebRequest -Uri "https://도메인/go/creative-id" -MaximumRedirection 0 -UseBasicParsing
} catch {
  $r = $_.Exception.Response
}

[pscustomobject]@{
  Status = [int]$r.StatusCode
  Location = $r.Headers.Location
}

정상 예:

Status: 302
Location: https://목적지/

11. 스크린샷이 필요한 순간에는 멈추기

바이브코딩으로 문서를 만들 때도 실제 화면이 중요합니다. 특히 API, DB, 도메인 연결 화면은 서비스마다 바뀔 수 있습니다.

그래서 필요한 화면이 있으면 AI가 상상해서 쓰는 게 아니라, 작업을 멈추고 사용자에게 스크린샷을 요청하는 방식이 좋습니다.

요청 예:

여기서 실제 화면 스크린샷이 필요합니다.

Supabase에서 아래 화면을 열어주세요.

Project
→ Connect
→ Direct
→ Connection string

비밀번호와 전체 DATABASE_URL은 가리고,
Connection string 영역과 host/port/database 항목이 보이게 캡처해주세요.

이 방식이 좋은 이유:


12. 검색 콘텐츠에 광고를 붙일 때 주의할 점

웹서비스를 만들다 보면 답변 페이지에 CTA를 붙이고 싶어집니다. 하지만 광고는 검색 의도와 맞을 때만 붙여야 합니다.

예를 들어:

미용실 고객관리 방법
→ SalonNote CTA 적합

하지만:

태국 입국카드 작성법
→ 미용실 관리 프로그램 CTA 부적합

관련 없는 CTA는 클릭률보다 페이지 품질을 떨어뜨릴 가능성이 큽니다. 검색자가 해결하려는 문제와 광고가 맞지 않으면 과감히 빼는 편이 좋습니다.


13. 최종 요약

바이브코딩으로 웹 하나를 만들 때 중요한 건 코드 생성 자체가 아니라, 실제 운영 연결을 끝까지 확인하는 것입니다.

최소한 아래까지 확인해야 “작동하는 웹”이라고 할 수 있습니다.

GitHub push 완료
Render 배포 완료
Supabase DATABASE_URL 연결
Prisma migration 완료
Seed 데이터 저장
도메인 연결
HTTPS 접속 정상
DB health 정상
API Key는 환경변수로 분리
Secret 노출 없음
lint/typecheck/test/build 통과

이 과정을 한 번 만들어두면, 다음 웹서비스를 만들 때는 같은 흐름을 반복하면 됩니다. 바이브코딩은 시작을 빠르게 해주지만, 실제 서비스 품질은 이런 운영 연결과 검증에서 결정됩니다.