강동민
Windows 웹 배포 가이드

내가 만든 웹페이지
인터넷에 올리기

GitHub에 보관하고, Vercel로 배포하고, Supabase에 데이터를 저장하기까지. 아무것도 설치하지 않은 Windows PC에서 브라우저만으로 끝내는 전 과정입니다.

소요 시간 약 60분 Windows 10 / 11 설치 프로그램 없음 명령어 입력 없음 무료 플랜으로 가능

시작하기 전에 준비할 것

세 가지 도구가 각각 하는 일

GitHub

파일 보관소

내 웹페이지 파일을 인터넷에 보관합니다. 언제 무엇을 고쳤는지 기록이 남고, 실수해도 되돌릴 수 있습니다.

Vercel

배포와 주소

GitHub에 있는 파일을 실제 웹사이트로 띄우고 주소를 줍니다. 파일을 고치면 알아서 다시 배포합니다.

Supabase

데이터 저장

방문자가 남긴 글이나 신청 내역처럼 계속 쌓이는 데이터를 저장합니다. 새로고침해도 사라지지 않습니다.

내 PC의 파일→GitHub 저장소→Vercel→인터넷 주소
방문자의 브라우저↔Supabase 데이터베이스

파일은 GitHub를 거쳐 Vercel이 배포하고, 데이터는 방문자의 브라우저가 Supabase와 직접 주고받습니다. 그래서 서버를 직접 만들 필요가 없습니다.

1

계정 세 개 만들기

GitHub를 먼저 만들어야 합니다. Vercel과 Supabase는 GitHub 계정으로 로그인하는 방식을 쓰면 따로 아이디와 비밀번호를 만들지 않아도 되고, 나중 단계에서 연결도 저절로 됩니다.

1-1. GitHub 계정

  1. 주소창에 github.com/signup을 입력해 엽니다.
  2. Email에 내 이메일 주소를 적습니다.
  3. Password에 비밀번호를 적습니다. 15자 이상이거나, 8자 이상이면서 숫자와 소문자를 포함해야 합니다.
  4. Username에 영문 아이디를 적습니다. 이 아이디가 나중에 github.com/아이디 주소가 됩니다. 한글과 공백은 쓸 수 없습니다.
  5. Your Country/Region에서 Korea, South를 고릅니다.
  6. Create account를 누릅니다.
  7. 이메일로 온 여섯 자리 숫자를 화면에 입력하면 가입이 끝납니다.
GitHub 가입 화면의 입력란과 Create account 버튼
[ 화면 ]
GitHub 가입github.com/signup 화면.
그림 1. GitHub 가입 화면. 네 칸을 채우고 Create account를 누릅니다.
Copilot Free 체크박스는 그대로 둬도 됩니다. 무료이고, 이 가이드의 진행에는 영향이 없습니다. 원치 않으면 체크를 풀어도 됩니다.

1-2. Vercel 계정

  1. vercel.com/signup을 엽니다.
  2. Continue with GitHub를 누릅니다.
  3. GitHub 화면이 뜨면 Authorize Vercel을 눌러 허용합니다.
  4. 이름을 묻는 화면이 나오면 적고 넘어갑니다. 플랜을 고르라고 하면 Hobby(무료)를 고릅니다.
  5. Secure Your Account with 2FA 화면이 나오면 아래 "가입 중에 나오는 2단계 인증 화면"을 보고 고릅니다. 지금 건너뛰어도 가입은 그대로 끝납니다.
Vercel 가입 화면의 Continue with GitHub 버튼
[ 화면 ]
Vercel 가입vercel.com/signup 화면.
그림 2. Vercel 가입. Continue with GitHub로 시작하면 뒤가 편합니다.

1-2-1. "Secure Your Account with 2FA" 화면이 나오면

가입은 이미 끝난 상태입니다. 연습용이면 아래 작은 글씨 Skip securing my account를 눌러 넘어갑니다. 남이 쓸 사이트라면 Set Up Authenticator App으로 켜고 마지막에 나오는 복구 코드를 안전한 곳에 보관합니다.

1-3. Supabase 계정

  1. supabase.com/dashboard/sign-up을 엽니다.
  2. Continue with GitHub를 누르고, GitHub 화면에서 허용합니다.
  3. 조직(Organization) 이름을 물으면 아무 이름이나 적습니다. 본인 이름도 괜찮습니다. 플랜은 Free를 고릅니다.
Supabase 가입 화면의 Continue with GitHub 버튼
[ 화면 ]
Supabase 가입supabase.com 가입 화면.
그림 3. Supabase 가입. 여기서도 GitHub 계정으로 로그인합니다.
세 화면 모두 영어입니다. 번역이 필요하면 Chrome에서 화면 아무 곳이나 오른쪽 클릭한 뒤 한국어로 번역을 누르면 됩니다. 다만 번역된 상태에서는 버튼 이름이 이 가이드와 달라 보이므로, 헷갈리면 원문으로 되돌리세요.
여기까지 확인
  • 브라우저 탭 세 개에서 github.com, vercel.com/dashboard, supabase.com/dashboard가 각각 로그인된 상태로 열린다.
  • 세 화면 어디에서도 로그인이나 가입을 다시 요구하지 않는다.

한 곳이라도 로그인 화면으로 돌아간다면 그 서비스의 가입을 끝내지 못한 것입니다. 다음 단계로 넘어가기 전에 마무리하세요.

2

올릴 파일 준비하기

배포에는 규칙이 하나 있습니다. 첫 화면이 될 파일의 이름은 반드시 index.html이어야 합니다. 소문자로 정확히 그 이름이어야 하고, 폴더 맨 바깥(최상단)에 있어야 합니다. 이 규칙만 지키면 나머지는 자유입니다.

이미 만든 페이지가 있다면

  • 첫 화면 파일 이름을 index.html로 바꿉니다.
  • 이미지, CSS, JS 같은 딸린 파일은 같은 폴더 구조 그대로 함께 올립니다.
  • 파일 이름에 한글, 공백, 괄호가 있으면 영문과 하이픈으로 바꿉니다. 예: 내 사진 (1).png → photo-1.png. 바꾼 뒤에는 HTML 안에서 그 파일을 부르는 부분도 같이 고쳐야 합니다.

없다면 이 예제로 시작하세요

아래 코드가 이 가이드에서 끝까지 쓰는 예제 페이지입니다. 자기소개 한 줄과 방명록이 있는 한 장짜리 페이지이고, 파일은 index.html 하나뿐입니다. 지금은 데이터베이스가 연결되지 않은 상태라 방명록 자리에 안내문이 보이고, 5단계와 6단계를 마치면 실제로 글이 쌓입니다.

예제 index.html 전체 코드 (눌러서 펼치고 복사)
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>내 웹페이지</title>
<style>
  :root{ --bg:#f6f7f9; --card:#fff; --ink:#1b2030; --muted:#5b6472; --line:#e6e8ee; --accent:#3f5bd9; }
  *{box-sizing:border-box}
  body{margin:0;background:var(--bg);color:var(--ink);
       font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Malgun Gothic",sans-serif;line-height:1.7}
  .wrap{max-width:640px;margin:0 auto;padding:56px 20px 80px}
  h1{font-size:34px;margin:0 0 8px}
  .sub{color:var(--muted);margin:0 0 32px}
  .card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:22px 24px;margin:0 0 20px}
  h2{font-size:18px;margin:0 0 14px}
  label{display:block;font-size:14px;color:var(--muted);margin:12px 0 6px}
  input,textarea{width:100%;padding:11px 13px;border:1px solid var(--line);border-radius:9px;
                 font:inherit;background:#fff;color:var(--ink)}
  textarea{min-height:88px;resize:vertical}
  button{margin-top:16px;width:100%;padding:12px;border:0;border-radius:9px;background:var(--accent);
         color:#fff;font:inherit;font-weight:700;cursor:pointer}
  button:disabled{opacity:.5;cursor:default}
  .msg{margin-top:12px;font-size:14px;color:var(--muted);min-height:20px}
  .entry{border-top:1px solid var(--line);padding:14px 0}
  .entry:first-child{border-top:0}
  .entry b{display:block}
  .entry time{font-size:12.5px;color:var(--muted)}
  .notice{background:#fef4ec;border:1px solid #e2a06a;border-radius:10px;padding:14px 16px;font-size:14.5px}
</style>
</head>
<body>
<div class="wrap">

  <h1>안녕하세요, 강동민입니다</h1>
  <p class="sub">이 페이지는 GitHub에 올려 Vercel로 배포했습니다.</p>

  <section class="card">
    <h2>방명록 남기기</h2>
    <form id="guestbook-form">
      <label for="name">이름</label>
      <input id="name" maxlength="20" required placeholder="이름을 적어 주세요">
      <label for="message">한마디</label>
      <textarea id="message" maxlength="200" required placeholder="하고 싶은 말을 적어 주세요"></textarea>
      <button type="submit" id="submit-btn">남기기</button>
    </form>
    <p class="msg" id="form-msg"></p>
  </section>

  <section class="card">
    <h2>남겨진 글</h2>
    <div id="entries"><p class="msg">불러오는 중...</p></div>
  </section>

</div>

<!-- Supabase 라이브러리 -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script>
  // 여기 두 줄만 내 값으로 바꿉니다 (가이드 6단계)
  const SUPABASE_URL = "";
  const SUPABASE_KEY = "";

  const entriesEl = document.getElementById("entries");
  const formEl = document.getElementById("guestbook-form");
  const msgEl = document.getElementById("form-msg");
  const btnEl = document.getElementById("submit-btn");

  const connected = SUPABASE_URL !== "" && SUPABASE_KEY !== "";
  const db = connected ? supabase.createClient(SUPABASE_URL, SUPABASE_KEY) : null;

  if (!connected) {
    entriesEl.innerHTML =
      '<div class="notice">아직 데이터베이스를 연결하지 않았습니다. ' +
      "가이드의 데이터베이스 단계를 마치고 index.html 위쪽 두 줄을 채우면 " +
      "여기에 방명록이 쌓입니다.</div>";
    btnEl.disabled = true;
  } else {
    loadEntries();
  }

  async function loadEntries() {
    const { data, error } = await db
      .from("guestbook")
      .select("*")
      .order("created_at", { ascending: false })
      .limit(50);

    if (error) {
      entriesEl.innerHTML = '<p class="msg">불러오지 못했습니다: ' + error.message + "</p>";
      return;
    }
    if (!data.length) {
      entriesEl.innerHTML = '<p class="msg">아직 남겨진 글이 없습니다.</p>';
      return;
    }
    entriesEl.innerHTML = data
      .map(function (row) {
        return (
          '<div class="entry"><b>' +
          escapeHtml(row.name) +
          "</b>" +
          escapeHtml(row.message) +
          "<time>" +
          new Date(row.created_at).toLocaleString("ko-KR") +
          "</time></div>"
        );
      })
      .join("");
  }

  formEl.addEventListener("submit", async function (event) {
    event.preventDefault();
    btnEl.disabled = true;
    msgEl.textContent = "저장하는 중...";

    const { error } = await db.from("guestbook").insert({
      name: document.getElementById("name").value.trim(),
      message: document.getElementById("message").value.trim(),
    });

    if (error) {
      msgEl.textContent = "저장하지 못했습니다: " + error.message;
    } else {
      msgEl.textContent = "남겼습니다.";
      formEl.reset();
      loadEntries();
    }
    btnEl.disabled = false;
  });

  function escapeHtml(text) {
    return String(text).replace(/[&<>"']/g, function (ch) {
      return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[ch];
    });
  }
</script>
</body>
</html>

파일 만드는 법 (메모장으로 충분합니다)

  1. 바탕화면에서 오른쪽 클릭 후 새로 만들기 > 폴더를 눌러 my-webpage라는 폴더를 만듭니다.
  2. 그 폴더 안에서 오른쪽 클릭 후 새로 만들기 > 텍스트 문서를 만듭니다.
  3. 메모장으로 열고 위 코드를 붙여 넣습니다.
  4. 파일 > 다른 이름으로 저장을 누릅니다. 파일 이름에 index.html, 파일 형식은 모든 파일, 인코딩은 UTF-8로 맞추고 저장합니다.
  5. 저장한 index.html을 더블클릭하면 브라우저에서 내 페이지가 열립니다.
인코딩을 UTF-8로 맞추지 않으면 한글이 깨집니다. 저장 창 아래쪽 인코딩 칸을 꼭 확인하세요. 이미 깨진 파일은 고치기 번거로우니, 저장할 때 한 번에 맞추는 편이 빠릅니다.
파일 형식을 "모든 파일"로 바꾸지 않으면 실제 이름이 index.html.txt가 됩니다. 겉보기에는 index.html처럼 보이는데 배포하면 화면이 안 뜹니다. 확인 방법은 아래 Windows에서만 겪는 함정에 있습니다.
예제 페이지를 브라우저에서 연 화면
[ 화면 ]
예제 페이지index.html을 브라우저로 연 모습.
그림 4. 예제 페이지를 브라우저에서 연 모습. 아래쪽 주황색 안내문은 아직 데이터베이스를 연결하지 않았다는 뜻이며, 6단계를 마치면 방명록 목록으로 바뀝니다.
지금 보이는 주소는 file:///C:/Users/...일 것입니다. 이것은 인터넷 주소가 아니라 내 컴퓨터 안의 파일 경로입니다. 이 주소를 다른 사람에게 보내면 열리지 않습니다. 진짜 주소는 4단계에서 받습니다.
여기까지 확인
  • 폴더 안에 index.html이 있고, 파일 확장명을 켠 상태에서 이름이 정확히 그렇게 보인다(index.html.txt가 아니다).
  • 더블클릭하면 브라우저에서 페이지가 열리고, 한글이 깨지지 않는다.

한글이 깨졌다면 메모장에서 다시 열어 다른 이름으로 저장 > 인코딩 UTF-8로 저장하면 됩니다.

3

GitHub에 파일 올리기

GitHub에 저장소(repository)를 하나 만들고, 그 안에 파일을 끌어다 놓습니다. 프로그램을 설치할 필요도, 명령어를 칠 필요도 없습니다.

3-1. 저장소 만들기

  1. 로그인한 상태로 github.com/new를 엽니다.
  2. Repository name에 영문 이름을 적습니다. 예: my-webpage. 공백 대신 하이픈을 씁니다.
  3. Choose visibility에서 Private를 고릅니다. 비공개로 두어도 Vercel 배포는 문제없이 됩니다. 소스를 공개하고 싶으면 Public을 골라도 됩니다.
  4. 아래의 Add README, Add .gitignore, Add license는 모두 그대로 둡니다.
  5. 맨 아래 Create repository를 누릅니다.
GitHub 새 저장소 만들기 화면
[ 화면 ]
새 저장소 만들기github.com/new 화면.
그림 5. 저장소 이름과 공개 범위만 정하면 됩니다. 나머지는 기본값 그대로 둡니다.

3-2. 파일 올리기

저장소를 만들면 아직 비어 있는 화면이 나옵니다. 가운데 파란 상자 안의 uploading an existing file을 누릅니다.

비어 있는 저장소 화면과 파일 업로드 링크
[ 화면 ]
빈 저장소저장소를 막 만든 직후 화면.
그림 6. 방금 만든 빈 저장소. 강조한 uploading an existing file을 누릅니다.
  1. 파일 탐색기에서 index.html을 포함한 파일들을 선택해 브라우저의 점선 상자 안으로 끌어다 놓습니다. 마우스로 끌어 놓는 대신 choose your files를 눌러 골라도 됩니다.
  2. 하위 폴더(예: images)가 있으면 폴더째로 끌어다 놓으면 구조가 유지됩니다.
  3. 아래 Commit changes 칸에는 아무 설명이나 적어도 되고, 비워 두면 자동으로 채워집니다.
  4. 초록색 Commit changes 버튼을 누릅니다.
파일을 끌어다 놓는 업로드 화면
[ 화면 ]
파일 업로드드래그 앤 드롭 영역과 Commit changes 버튼.
그림 7. 점선 영역에 파일을 끌어다 놓고, 아래 Commit changes를 누릅니다.

3-3. 잘 올라갔는지 확인

저장소 첫 화면으로 돌아오면 파일 목록이 보입니다. index.html이 목록 맨 바깥에 있는지 꼭 확인하세요. 폴더 안에 들어가 있으면 다음 단계에서 페이지가 안 뜹니다.

저장소에 올라온 파일 목록
[ 화면 ]
파일 목록업로드가 끝난 저장소 화면.
그림 8. index.html이 최상단에 보이면 정상입니다.
나중에 파일을 고칠 때도 같은 자리에서 합니다. 같은 이름의 파일을 다시 업로드하면 덮어쓰기가 되고, 파일 이름을 눌러 들어간 뒤 연필 아이콘을 누르면 브라우저에서 바로 고칠 수도 있습니다. 6단계에서 이 방법을 씁니다.
여기까지 확인
  • 저장소 첫 화면의 파일 목록에 index.html이 바로 보인다(폴더를 열고 들어가지 않아도 된다).
  • 파일 이름을 누르면 내가 쓴 코드 내용이 그대로 보인다.
  • 화면 위쪽에 1 Commit처럼 커밋 기록이 하나 이상 있다.
4

Vercel로 배포하기

이제 GitHub에 있는 파일을 실제 웹사이트로 띄웁니다. 여기까지 하면 누구나 접속할 수 있는 주소가 생깁니다.

4-1. 저장소 가져오기

  1. 로그인한 상태로 vercel.com/new를 엽니다.
  2. Import Git Repository 목록에서 방금 만든 저장소(my-webpage)를 찾아 오른쪽 Import를 누릅니다.
Vercel의 저장소 가져오기 목록
[ 화면 ]
저장소 가져오기vercel.com/new 화면의 Import 목록.
그림 9. 목록에서 내 저장소를 찾아 Import를 누릅니다.
목록에 내 저장소가 안 보인다면 Vercel에게 그 저장소를 볼 권한이 없는 것입니다. 목록 아래의 Adjust GitHub App Permissions(또는 계정 선택 옆의 설정 링크)를 눌러 All repositories를 허용하거나, 해당 저장소를 골라 추가한 뒤 돌아오면 나타납니다.

4-2. 설정 확인하고 배포

  1. Project Name은 그대로 두어도 됩니다. 이 이름이 주소의 앞부분이 됩니다.
  2. Application Preset(또는 Framework Preset)이 Other인지 확인합니다. HTML 파일만 있는 페이지는 Other가 맞습니다.
  3. Root Directory는 ./ 그대로 둡니다. 단, GitHub에서 파일이 폴더 안에 들어가 있다면 Edit를 눌러 그 폴더를 골라야 합니다.
  4. Build and Output Settings와 Environment Variables는 건드리지 않습니다.
  5. Deploy를 누릅니다.
Vercel 프로젝트 설정 화면
[ 화면 ]
배포 설정프리셋과 Deploy 버튼.
그림 10. 프리셋이 Other인지만 보고 Deploy를 누릅니다. (팀 이름은 개인 정보라 가렸습니다.)

4-3. 주소 확인

보통 10초에서 1분 사이에 배포가 끝나고 Congratulations! 화면이 나옵니다. 가운데 미리보기에 내 페이지가 그대로 보이면 성공입니다.

배포 성공을 알리는 Congratulations 화면
[ 화면 ]
배포 성공Congratulations 화면과 페이지 미리보기.
그림 11. 배포가 끝난 직후 화면. 미리보기 속 페이지가 방금 올린 내 index.html입니다. (계정 이름은 가렸습니다.)

미리보기 이미지나 아래쪽 Continue to Dashboard를 누르면 프로젝트 화면으로 갑니다. 여기서 Domains 아래 주소가 내 웹사이트 주소입니다. 보통 프로젝트이름.vercel.app 형태입니다.

배포가 끝난 Vercel 프로젝트 화면
[ 화면 ]
배포 완료Status가 Ready이고 주소가 보이는 화면.
그림 12. 상태가 Ready가 되면 배포가 끝난 것입니다. 강조한 주소가 내 사이트 주소이고, 오른쪽 위 Visit으로 바로 열 수 있습니다. (계정 정보는 가렸습니다.)
주소를 휴대폰으로도 열어 보세요. 진짜 인터넷에 올라간 것이라 다른 기기, 다른 사람도 그대로 볼 수 있습니다. 여기까지가 "배포"의 전부입니다.
이제부터는 GitHub만 고치면 됩니다. GitHub의 파일을 바꾸면 Vercel이 그 변화를 감지해 자동으로 다시 배포합니다. Vercel 화면에 다시 올 일은 거의 없습니다.
여기까지 확인
  • Vercel 프로젝트 화면의 Status가 Ready다.
  • Domains의 짧은 주소를 브라우저 주소창에 붙여 넣으면 내 페이지가 열린다.
  • 휴대폰(또는 다른 사람의 기기)에서도 같은 주소가 열린다.

데이터를 받을 일이 없는 페이지라면 여기서 끝내도 됩니다. 방명록, 신청서, 문의처럼 방문자 입력을 저장해야 한다면 5단계로 이어집니다.

5

Supabase에 표 만들기

지금 페이지는 글을 남겨도 저장할 곳이 없습니다. Supabase에 표(table)를 하나 만들어 그 자리를 마련합니다. 엑셀 시트를 하나 만든다고 생각하면 됩니다.

이미 만든 내 페이지를 쓰고 있다면 여기부터는 그 페이지에 방명록 같은 입력 기능이 있어야 의미가 있습니다. 없다면 2단계의 예제 코드에서 <form>부터 </script>까지를 통째로 복사해 내 페이지에 붙여 넣으면 같은 방명록이 생깁니다. 붙여 넣을 위치는 </body> 바로 위입니다.

5-1. 프로젝트 만들기

  1. supabase.com/dashboard를 열고 New project를 누릅니다.
  2. Project name에 영문 이름을 적습니다. 예: my-webpage.
  3. Database Password는 Generate a password를 눌러 만들고, 따로 적어 둡니다. 이 가이드에서는 쓰지 않지만 나중에 필요할 때 다시 볼 수 없습니다.
  4. Region은 Northeast Asia (Seoul)을 고릅니다. 한국에서 접속할 때 가장 빠릅니다.
  5. 아래 Security의 체크박스 세 개는 기본값 그대로 둡니다. 위의 두 개가 켜져 있어야 브라우저가 데이터베이스와 대화할 수 있습니다.
  6. Create new project를 누르고 1분에서 2분 정도 기다립니다.
Supabase 새 프로젝트 입력 화면
[ 화면 ]
새 프로젝트 만들기이름, 비밀번호, 리전 입력 화면.
그림 13. 채울 것은 사실상 이름과 리전 둘뿐입니다. 비밀번호는 Generate a password로 만들고 따로 적어 둡니다. GitHub 연결은 건너뛰어도 됩니다.
데이터베이스 비밀번호는 이 화면에서만 볼 수 있습니다. 나중에 다시 확인할 수 없고 재설정만 가능합니다. 이 가이드에서는 쓸 일이 없지만, 메모장이나 비밀번호 관리자에 붙여 두세요.

준비가 끝나면 아래 같은 화면이 나옵니다. 제목 아래에 https://...supabase.co 형태의 주소가 보이면 완성입니다. 이 주소는 6단계에서 씁니다.

Supabase 프로젝트 첫 화면과 프로젝트 주소
[ 화면 ]
프로젝트 첫 화면Status가 Healthy이고 주소가 보이는 화면.
그림 14. 프로젝트가 준비된 화면. 강조한 것이 Project URL이고, 옆의 Copy로 복사합니다.
무료 플랜은 프로젝트를 2개까지 활성 상태로 둘 수 있습니다. 이미 두 개가 있으면 새로 만들 수 없다는 안내가 나옵니다. 대처법은 문제 해결에 있습니다.

5-2. SQL Editor 열기

프로젝트가 준비되면 위 그림 같은 Project Overview 화면에 서 있게 됩니다. 여기서 바로 표를 만들 수는 없고, 왼쪽 메뉴로 자리를 한 번 옮겨야 합니다.

  1. 화면 맨 왼쪽 끝을 봅니다. 아이콘만 세로로 늘어선 좁은 띠가 있습니다. 글씨가 없어서 메뉴처럼 보이지 않지만 이것이 프로젝트 메뉴입니다.
  2. 그 띠에 마우스를 올리면 폭이 넓어지면서 이름이 나타납니다. 위에서부터 Project Overview, Table Editor, SQL Editor, Database, Authentication, Storage 순입니다.
  3. 위에서 세 번째 SQL Editor를 누릅니다. 아이콘은 >_ 모양입니다. 키보드로는 G를 누르고 이어서 S를 눌러도 같은 화면으로 갑니다.
  4. 빈 편집기가 열립니다. 가운데 넓은 칸에 Hit CTRL+SHIFT+K to generate query or just start typing이라는 흐린 안내가 있고, 오른쪽 위에 초록색 Run 버튼이 있습니다. 아래쪽에는 Results 칸이 비어 있습니다. 여기가 다음 절에서 코드를 붙여 넣을 자리입니다.
왼쪽 띠가 안 보인다면 화면 왼쪽 아래 구석의 작은 사각형 아이콘을 누르면 메뉴가 접히고 펴집니다. 실수로 접어 둔 상태일 수 있습니다.

5-3. SQL 한 번 붙여 넣기

표를 만들고, 누가 읽고 쓸 수 있는지까지 한 번에 정합니다. 방금 연 SQL Editor의 빈 칸에 아래 코드를 전부 붙여 넣고 오른쪽 위 Run을 누릅니다. 코드 블록 오른쪽 위의 복사 버튼을 쓰면 한 번에 복사됩니다. 아래 Results 칸에 Success. No rows returned가 뜨면 성공입니다.

SQL Editor에 붙여 넣을 코드
create table guestbook (
  id bigint generated always as identity primary key,
  name text not null,
  message text not null,
  created_at timestamptz not null default now()
);

alter table guestbook enable row level security;

create policy "누구나 읽기" on guestbook
  for select to anon using (true);

create policy "누구나 쓰기" on guestbook
  for insert to anon with check (true);
SQL Editor에 코드를 붙여 넣은 화면
[ 화면 ]
SQL 편집기코드를 붙여 넣고 Run을 누르기 직전 화면.
그림 15. 코드를 붙여 넣고 오른쪽 위 Run을 누릅니다. 아래에 Success. No rows returned가 나오면 성공입니다.

5-4. 확인

확인도 5-2에서 쓴 왼쪽 아이콘 띠로 자리를 옮겨서 합니다. 띠에서 네 번째 Database를 누르면 가운데에 하위 목록이 생기는데, 그중 Policies를 누릅니다. guestbook 표 아래에 정책 두 개가 보이면 제대로 된 것입니다. 같은 띠의 두 번째 Table Editor로 가면 방금 만든 표가 목록에 보입니다.

Supabase의 정책 목록 화면
[ 화면 ]
정책 확인Database > Policies 화면.
그림 16. 정책 화면. 표마다 어떤 정책이 걸려 있는지 여기서 봅니다. guestbook 아래에 INSERT와 SELECT 정책이 하나씩 보이면 정상입니다. 정책이 하나도 없는 표에는 "No data will be returned"라고 표시됩니다.
6

주소와 키를 페이지에 넣기

마지막으로 내 페이지에게 "데이터는 여기에 저장해"라고 알려 줍니다. 값 두 개만 넣으면 됩니다.

6-1. 값 두 개 복사하기

  1. Project URL: 5단계 그림 14의 화면 위쪽에 있는 https://...supabase.co 주소입니다. Copy를 눌러 복사합니다.
  2. Publishable key: 왼쪽 아래 톱니바퀴(Project Settings) > API Keys로 갑니다. Publishable key 칸의 sb_publishable_...로 시작하는 값을 복사 아이콘으로 복사합니다.
Supabase API Keys 화면
[ 화면 ]
API 키Project Settings > API Keys 화면.
그림 17. 위쪽 Publishable key를 복사합니다. 아래 Secret keys는 절대 쓰지 않습니다. (실제 키 값은 가렸습니다.)
Secret key는 페이지에 넣으면 안 됩니다. 이름 그대로 비밀 키이고, 이 키가 있으면 잠금장치를 전부 무시하고 데이터를 지울 수도 있습니다. 웹페이지에 넣는 것은 Publishable key뿐입니다. 예전 화면에서는 이 둘을 anon과 service_role이라고 불렀습니다.
Publishable key는 공개돼도 괜찮습니다. 브라우저에 그대로 실리기 때문에 누구나 볼 수 있고, 원래 그렇게 쓰라고 만든 키입니다. 대신 5단계에서 켠 RLS 정책이 실제 방어선 역할을 합니다. 그래서 정책을 대충 열어 두면 안 됩니다.

6-2. index.html에 붙여 넣기

고치는 자리를 여기서 한 번 정하고 갑니다. 아래는 GitHub 화면에서 바로 고치는 방법입니다. 파일을 GitHub에만 두고 쓸 사람은 이대로 하면 됩니다. 반대로 내 PC에 작업용 원본을 두고 앞으로도 거기서 고쳐 나갈 사람은, 여기서도 내 PC의 index.html에 두 줄을 채운 뒤 Add file > Upload files로 덮어쓰는 편이 낫습니다. 결과는 똑같고, 내 PC 원본과 GitHub 파일이 어긋나지 않습니다.
  1. GitHub 저장소에서 index.html을 누릅니다.
  2. 파일 내용 오른쪽 위의 연필 아이콘을 눌러 편집 화면을 엽니다.
  3. 편집 화면 안을 한 번 클릭한 뒤 Ctrl + F를 누르고 SUPABASE_URL을 입력하면 해당 줄로 바로 이동합니다. 마우스로 내려서 찾아도 됩니다(60행 부근).
GitHub 웹 편집기에서 설정 두 줄을 찾은 화면
[ 화면 ]
고쳐야 할 두 줄GitHub 웹 편집기 화면.
그림 18. 이 두 줄의 따옴표 안에 복사한 값을 넣습니다.
고치기 전
const SUPABASE_URL = "";
const SUPABASE_KEY = "";
고친 뒤 (값은 각자 자기 것으로)
const SUPABASE_URL = "https://abcdefghijklmnop.supabase.co";
const SUPABASE_KEY = "sb_publishable_XXXXXXXXXXXXXXXXXXXXXX";
  • 따옴표 "는 지우지 말고 그 안에만 붙여 넣습니다.
  • 줄 끝의 세미콜론 ;도 그대로 둡니다.
  • 주소 끝에 /가 붙어 있으면 지웁니다.

다 고쳤으면 오른쪽 위 Commit changes...를 누릅니다. 창이 하나 뜨는데, 설명은 비워 두어도 되고 Commit directly to the main branch가 선택된 그대로 두면 됩니다. 초록색 Commit changes를 눌러 저장합니다.

6-3. 자동 재배포 확인

저장하는 순간 Vercel이 알아서 다시 배포합니다. Vercel 프로젝트의 Deployments 화면에 새 줄이 하나 생기고, 상태가 Ready로 바뀌면 끝입니다. 보통 1분 안에 끝납니다.

Vercel의 배포 이력 목록
[ 화면 ]
재배포 이력Deployments 목록 화면.
그림 19. 파일을 고칠 때마다 이 목록에 한 줄씩 쌓입니다. 맨 위가 지금 살아 있는 배포입니다.
화면이 그대로여도 당황하지 마세요. 브라우저가 이전 파일을 기억하고 있을 수 있습니다. Ctrl + Shift + R을 눌러 강력 새로고침하면 최신 파일로 다시 받아옵니다.

이제 내 주소로 접속해 이름과 한마디를 적고 남기기를 눌러 보세요. 주황색 안내문이 사라지고 남긴 글이 아래 목록에 나타납니다.

방명록이 실제로 동작하는 완성된 페이지
[ 화면 ]
완성된 페이지방명록에 글이 쌓인 화면.
그림 20. 실제로 배포된 주소에서 글을 두 건 남긴 모습. 이름, 내용, 남긴 시각이 함께 저장됩니다.
여기까지 확인
  • 배포된 주소에서 남기기 버튼이 눌린다(회색으로 비활성화돼 있지 않다).
  • 글을 남기면 남겼습니다.라는 문구가 뜨고, 아래 목록에 방금 쓴 글이 나타난다.
  • 페이지를 새로고침해도 그 글이 그대로 있다.

빨간 오류 문구가 뜬다면 그 문구를 그대로 문제 해결에서 찾아보세요. 대부분 정책(RLS) 아니면 주소, 키 오타입니다.

배포 완료

여기까지 왔다면 세 가지가 모두 연결된 것입니다. 새로고침해도, 브라우저를 껐다 켜도, 휴대폰에서 열어도 그 글은 그대로 남아 있습니다. 내 PC가 꺼져 있어도 마찬가지입니다.

7

확인하고 마무리하기

7-1. 저장이 실제로 됐는지 확인

Supabase의 Table Editor에서 왼쪽 목록의 guestbook을 눌러 보세요. 방금 남긴 글이 한 줄씩 들어와 있으면 진짜로 저장된 것입니다. 여기서 이상한 글을 직접 지울 수도 있습니다(줄 왼쪽 체크 후 삭제).

Table Editor에 저장된 방명록 데이터
[ 화면 ]
저장된 데이터guestbook 표에 두 줄이 들어온 화면.
그림 21. 웹페이지에서 남긴 글이 데이터베이스에 그대로 들어와 있습니다. id는 자동으로 붙는 번호이고, created_at도 자동으로 채워집니다. (다른 표 이름은 가렸습니다.)

7-2. 앞으로 페이지를 고치는 방법

GitHub에서 파일을 열고 연필 아이콘을 눌러 고친 뒤 Commit changes를 누르면 됩니다. 그때마다 Vercel이 1분 안에 다시 배포합니다. 잘못 고쳤으면 그 파일의 History에서 예전 버전을 열어 되돌립니다.

7-3. 알아 둘 한 가지

Supabase 무료 플랜은 일주일 동안 아무도 안 들어오면 프로젝트를 일시정지합니다. 그러면 방명록만 안 되고 페이지는 그대로 열립니다. 대시보드에서 Restore를 누르면 다시 살아나고 데이터는 지워지지 않습니다.


Windows에서만 겪는 함정

1. 확장자가 숨겨져 있습니다. Windows는 기본적으로 .html, .txt 같은 확장자를 감춥니다. 그래서 index.html.txt가 화면에는 index.html로 보입니다. 파일 탐색기에서 보기 > 표시 > 파일 확장명에 체크하면(Windows 10은 보기 탭의 파일 확장명) 진짜 이름이 보입니다. 배포하기 전에 반드시 한 번 켜서 확인하세요.
2. 대문자와 소문자를 구분하지 않습니다. 내 PC에서는 Style.css와 style.css가 같은 파일 취급이라 잘 열립니다. 그런데 배포된 서버는 이 둘을 다른 파일로 봅니다. 그래서 "내 컴퓨터에서는 되는데 배포하니 디자인이 깨진다"가 생깁니다. HTML에 적은 파일 이름과 실제 파일 이름의 대소문자를 글자 하나까지 똑같이 맞추세요.
3. 메모장 저장 인코딩. 저장할 때 인코딩을 UTF-8로 맞추지 않으면 배포 후 한글이 ?나 깨진 글자로 나옵니다. "UTF-8(BOM)"이 아니라 그냥 UTF-8이면 가장 무난합니다.
메모장이 불편하면 무료 편집기를 하나 깔아도 됩니다. Visual Studio Code는 확장자, 인코딩, 대소문자를 모두 눈에 보이게 다뤄 주어서 위 함정 대부분을 자동으로 피하게 해 줍니다. 설치 없이 끝내고 싶다면 GitHub의 연필 아이콘(웹 편집기)만 써도 충분합니다.

문제 해결

배포는 됐는데 404 NOT_FOUND가 뜹니다

거의 항상 원인은 셋 중 하나입니다. 첫째, 첫 화면 파일 이름이 index.html이 아닙니다(대문자 Index.html도 안 됩니다). 둘째, index.html이 폴더 안에 들어가 있습니다. 이 경우 Vercel 프로젝트의 Settings > General > Root Directory를 그 폴더로 바꾸면 됩니다. 셋째, 진짜 파일 이름이 index.html.txt입니다. GitHub 저장소 파일 목록에서 실제 이름을 눈으로 확인하세요.

메모장에서 코드를 붙여 넣었더니 줄이 다 붙어 버립니다

메모장 상단 메뉴에서 서식 > 자동 줄 바꿈을 꺼도 되지만, 사실 화면에 어떻게 보이든 저장되는 내용은 같습니다. 코드 블록 오른쪽 위의 복사 버튼으로 복사했다면 줄바꿈은 그대로 들어가 있으니 그냥 저장하면 됩니다.

고쳤는데 사이트에 예전 화면이 그대로입니다

순서대로 확인하세요. 1) GitHub에서 실제로 커밋이 됐는지(파일 목록에 방금 시각이 찍혔는지), 2) Vercel의 Deployments에 새 줄이 생겼고 상태가 Ready인지, 3) 브라우저 캐시인지. 셋째라면 Ctrl + Shift + R로 강력 새로고침하거나 시크릿 창에서 열어 보세요.

글을 남기면 "new row violates row-level security policy"가 뜹니다

쓰기 정책이 없다는 뜻입니다. 5단계 SQL에서 create policy "누구나 쓰기" 부분이 실행되지 않았을 가능성이 큽니다. SQL Editor에서 아래 한 덩어리만 다시 실행하세요.

create policy "누구나 쓰기" on guestbook
  for insert to anon with check (true);
"Invalid API key"가 뜹니다

키를 복사하다 앞뒤 공백이나 줄바꿈이 섞였거나, 키 일부만 복사된 경우입니다. API Keys 화면의 복사 아이콘을 눌러 다시 복사하고, 따옴표 안에 공백 없이 붙여 넣으세요.


태그배포GitHubVercelSupabase웹사이트호스팅무료정적사이트윈도우도메인
최종 수정: 2026-08-19
무료 AI 활용 진단 내 AI 활용 수준, 상위 몇 %일까요? 진단하면 내 점수와 지금 무엇부터 할지 알려드립니다.