콘텐츠로 이동

실제 백엔드 연결

03-first-run.md에서 console-log 모드로 첫 실행을 확인했다면, 이 단계에서는 같은 확장이 데이터를 진짜 백엔드로 보내게 바꿉니다. 30분에서 1시간 정도 걸립니다. 지금 당장 필요하지 않다면 건너뛰어도 됩니다.

모드어떤 분에게 맞나미리 준비할 것
supabase-direct백엔드 서버를 직접 굴리고 싶지 않은 분Supabase 프로젝트 (무료 티어로 충분), 프로젝트 URL, anon key
server-relay이미 서버를 운영 중이거나 곧 만들 분서버 URL과 인증 토큰

처음이라면 supabase-direct 가 빠릅니다. Supabase는 무료 티어에 데이터베이스, 인증, REST API가 같이 따라옵니다. 따로 서버를 띄울 일 없이 바로 행이 들어오는 모습을 볼 수 있습니다.

supabase.com 에서 무료로 가입한 다음 New project 를 누릅니다. 프로젝트 이름과 비밀번호를 정합니다. 리전은 가까운 곳을 고르세요. 한국에서는 Tokyo 또는 Singapore가 대기 시간 면에서 무난합니다.

프로젝트 프로비저닝이 끝나면 좌측 메뉴에서 Settings → API 로 갑니다. 이 페이지의 Project URLanon public 키 두 가지를 메모해 둡니다. 잠시 후 확장의 옵션 페이지에 이 두 값을 붙여 넣게 됩니다.

2) 데이터를 받을 테이블 만들기

섹션 제목: “2) 데이터를 받을 테이블 만들기”

Supabase 대시보드의 SQL Editor에서 다음 쿼리를 실행합니다. 이 base가 보내는 PageContent 모양에 맞는 가장 작은 테이블입니다.

create table public.page_contents (
id uuid primary key default gen_random_uuid(),
url text not null,
title text,
text_content text,
metadata jsonb,
links jsonb,
images jsonb,
created_at timestamptz default now()
);
-- anon 키로는 INSERT만 허용 (private 배포 가정)
alter table public.page_contents enable row level security;
create policy "anon insert"
on public.page_contents for insert
to anon
with check (true);

RLS(Row Level Security)에 대해 한 줄 짚어 두면, Supabase가 누가 무엇을 읽고 쓸 수 있는지를 제어하는 방식입니다. 위 정책은 anon 키로 행을 INSERT 할 수 있게 허용하면서 읽기는 막습니다. 그래서 확장 사용자들이 서로의 데이터를 끌어가는 일이 일어나지 않습니다.

  1. chrome://extensions 를 열고 본인 확장 카드에서 세부정보 를 누릅니다.
  2. 확장 프로그램 옵션 을 눌러 옵션 페이지를 엽니다.
  3. 백엔드 모드를 supabase-direct 로 바꾸고 앞서 메모한 Project URL과 anon key를 붙여 넣습니다.
  4. 저장합니다.

옵션 페이지를 열면 상단에 백엔드 모드를 고르는 라디오 버튼이 세 개 (console-log, supabase-direct, server-relay) 보입니다. supabase-direct 를 고르면 그 아래로 Project URL과 anon key 입력 칸 두 개가 새로 나타납니다. 두 칸을 모두 채우면 하단의 저장 버튼이 활성화됩니다. 저장 버튼이 회색으로 비활성 상태로 남아 있다면 두 입력 칸 중 하나가 비어 있거나, 붙여 넣은 값 끝에 공백 또는 줄바꿈이 따라 들어간 경우입니다.

Chrome에서 아무 페이지를 열고 확장 아이콘을 클릭한 다음 Analyze and send 를 누릅니다. Supabase 대시보드로 돌아가서 page_contents 의 Table Editor를 열면 새 행이 한 줄 들어와 있어야 합니다.

행이 안 보이면 06-troubleshooting.md의 “Supabase에 데이터가 들어오지 않습니다” 항목으로 갑니다.

서버는 다음 모양의 요청을 받을 수 있어야 합니다.

POST /api/page-content
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "...",
"title": "...",
"text_content": "...",
"metadata": { ... },
"links": [ ... ],
"images": [ ... ]
}

옵션 페이지에서 모드를 server-relay 로 바꾸고 서버 URL과 토큰을 붙여 넣은 다음 저장합니다. 확장은 2xx 응답이면 성공으로 봅니다.

옵션 페이지에서 모드를 console-log 로 바꾸고 저장하면 다시 외부 호출 없이 콘솔에만 찍히는 상태로 돌아옵니다. 이 토글은 언제든 왔다 갔다 할 수 있습니다. 백엔드 쪽이 잠깐 안 닿거나, 새 기능을 console-log 위에서 먼저 다듬고 싶을 때 자주 쓰게 됩니다.

  • 401 또는 403 에러: anon key 또는 토큰을 다시 복사합니다. 붙여 넣을 때 끝에 공백이나 줄바꿈이 같이 따라 들어가는 경우가 흔한 원인입니다.
  • CORS 에러: 서버가 확장의 origin (chrome-extension://...) 을 Access-Control-Allow-Origin 에 허용해야 합니다. server-relay 에서만 해당하는 이야기입니다. supabase-direct 는 supabase-js가 알아서 처리합니다.
  • 그 밖의 증상은 06-troubleshooting.md 의 백엔드 항목에 모여 있습니다.

한 발 더 — 내가 말한 시나리오대로 도는지

섹션 제목: “한 발 더 — 내가 말한 시나리오대로 도는지”

여기까지 오면 백엔드 한 줄까지는 데이터가 닿는 모습을 봤습니다. 다음 질문은 보통 이거입니다. “내가 처음에 말로 풀었던 시나리오대로 진짜 도나?”

이 질문은 손으로 한 번씩 클릭해서 확인할 수도 있지만, 시나리오가 두 개 세 개 늘어나면 매번 다 누르기가 번거롭습니다. base에는 그 자리를 자동으로 검사해 주는 도구가 한 개 박혀 있습니다. Claude Code에서 이렇게 부릅니다.

/test-extension

이 명령은 docs/design/extension-spec.md 의 §2 “사용 시나리오” 단락을 읽습니다. 거기 적은 한 줄짜리 시나리오를 AI가 직접 검증 코드로 변환합니다. 사용자는 시나리오를 적었을 뿐인데, AI가 그 시나리오를 실제로 함수 호출까지 내려가서 한 번 돌려 봅니다.

처음 부르면 Vitest라는 도구가 깔려 있지 않다고 한 번 물어봅니다. yes 라고 답하면 자동으로 깔린 다음 그 자리에서 검증까지 이어집니다. 결과는 익숙한 테스트 출력 그대로가 아니라, 시나리오 언어로 다시 적힌 보고서로 돌아옵니다.

총 시나리오: 5개 — 4개 통과, 1개 실패
✓ 페이지 컨텐츠 추출 — GitHub 이슈에서 제목, 본문, 라벨 정상 추출
✓ 백엔드 전송 — Bearer 토큰 + POST 정상
✗ PageContent 검증 — 빈 title 거절: 빈 title 이 들어왔는데 통과시켰다
파일: src/entities/page-content/__tests__/model.test.ts:8
고치는 곳: model/validate.ts 의 isValidPageContent

실패가 한 줄 나오면 그 자리에서 같은 Claude에게 “이거 고쳐줘” 라고 말하면 됩니다. 어디를 봐야 하는지가 보고서에 박혀 있어서 별도 설명을 다시 적어 줄 필요가 없습니다.

/test-extension 의 자세한 작동 원리 (시나리오를 어떻게 분해해서 어느 자리에 테스트 파일을 떨구는지, 정적 측 review-extension 과는 어떻게 다른지) 는 전문가용 검증 페이지에 있습니다.

데이터가 의도한 자리에 도착하는 모습까지 확인했다면 사용자에게 어떻게 전달할지로 넘어갑니다. 09-distribution.md에서 zip 직접 전달, Web Store 업로드, self-host .crx 셋의 트레이드오프를 풉니다.