"열심히 만들었는데, 새로고침하면 다 사라져요..." "다른 기기에서 들어가니까 제 할 일이 하나도 안 보여요."
맞아요. 22편에서 만든 앱은 기억상실증에 걸린 상태예요. 새로고침만 하면 모든 게 리셋되죠. 왜냐고요? 데이터를 내 브라우저의 임시 메모리에만 저장했으니까요.
이제 우리 앱에 영구적인 기억을 만들어줄 차례예요. 새로고침해도, 핸드폰으로 접속해도 내 할 일이 그대로 남아있게 만들어볼게요.
그러려면 **백엔드(Backend)**와 **데이터베이스(DB)**가 필요합니다. 겁먹지 마세요. 우리는 직접 서버를 만드는 게 아니라, Supabase라는 이미 잘 지어진 집을 빌려 쓸 거니까요.
이 글을 읽고 나면
- Supabase를 내 프론트엔드 프로젝트(Next.js)와 연결할 수 있어요
- **Auth(인증)**를 붙여서 진짜 '로그인' 기능을 구현할 수 있어요
- **CRUD(생성/조회/수정/삭제)**를 통해 데이터를 영구적으로 저장할 수 있어요
1. 큰 그림: 홀과 주방 연결하기
15편에서 배웠던 식당 비유, 기억나시죠?
- 프론트엔드 (Next.js): 손님이 있는 식당 홀 (22편에서 만듦)
- 백엔드 (Supabase): 요리가 만들어지는 주방 (오늘 연결함)
지금 상황은 홀 직원이 주방에 주문을 안 넣고, 그냥 종이에 적었다가 버리는 꼴이에요. 이제 주방과 홀을 연결하는 **인터폰(Supabase Client)**을 설치할 거예요.

우리는 AI한테 딱 3가지만 시키면 돼요.
- 인터폰 설치해줘 (Supabase 연결)
- 문지기 세워줘 (Auth 구현)
- 창고 써줘 (CRUD 구현)
2. 단계별 구현 가이드
1단계: Supabase 연결 (인터폰 설치)
먼저 우리 프로젝트(Next.js)가 Supabase와 대화할 수 있게 연결해야 해요.
🧑🏻💻 나 (사용자)
"우리 프로젝트에 Supabase 연결할 거야.
- 필요한 패키지(
@supabase/supabase-js) 설치해줘.lib/supabase.ts파일 만들어서 Supabase 클라이언트 설정해줘..env.local파일에 환경변수 들어갈 자리도 마련해줘."
🤖 AI
네, 패키지 설치하고 설정 파일을 만들게요.
.env.local파일에NEXT_PUBLIC_SUPABASE_URL과ANON_KEY를 넣을 준비를 해둘 테니, Supabase 대시보드에서 찾아서 채워주세요.
[!IMPORTANT] 휴먼터칠 시간! AI가 코드는 짜주지만, 비밀번호(API Key)는 여러분이 직접 넣어야 해요. Supabase 웹사이트 → Project Settings → API 메뉴에서 URL과 Key를 복사해서
.env.local파일에 붙여넣으세요.
2단계: 로그인/로그아웃 구현 (Auth)
연결이 됐으니 문지기를 세웁니다. 복잡한 보안 코드? 몰라도 돼요. "Supabase Auth 써줘" 한 마디면 됩니다.
🧑🏻💻 나 (사용자)
"로그인 기능을 만들자.
components/AuthButton.tsx컴포넌트를 만들어줘.기능:
- 로그인 안 했을 때: 'Google로 로그인' 버튼 보여주기
- 로그인 했을 때: '로그아웃' 버튼 보여주기
- Supabase Auth의
signInWithOAuth기능 사용해서 구현해줘."
🤖 AI
네, Supabase Auth를 사용해서 버튼을 만들게요. 구글 로그인을 사용하려면 Supabase 대시보드에서 Google Provider 설정을 켜야 해요.
3단계: 진짜 데이터 저장하기 (CRUD)
이제 가장 중요한 CRUD입니다. 메모리(Store)에 저장하던 걸 DB에 저장하도록 바꿀 거예요.
🧑🏻💻 나 (사용자)
"이제 DB랑 연동하자.
services/todoService.ts파일을 만들어줘.아까 만든
todos테이블이랑 연결해서 4가지 함수를 구현해줘:
- 가져오기 (Read):
select *로 내 할 일 목록 가져오기- 추가하기 (Create):
insert로 새 할 일 저장하기- 수정하기 (Update):
update로 완료 상태(is_completed) 바꾸기- 삭제하기 (Delete):
delete로 할 일 지우기그리고
zustand스토어(useTodoStore)를 수정해서, 이 서비스 함수들을 호출하게 해줘."
🤖 AI
알겠습니다.
services/todoService.ts에 Supabase 연결 함수들을 만들고,store/useTodoStore.ts에서 배열을 조작하는 대신 이 함수들을 부르도록 수정할게요.이제 데이터를 추가하면 진짜 DB에 저장됩니다!
3. 🎯 휴먼터치: 진짜 '저장'됐는지 확인하기
자, 코드는 AI가 다 짰습니다. 이제 진짜 **'서버'**에 저장되는지 검증해볼 시간이에요. 22편과는 확연히 다를 겁니다.
✅ 검증 체크리스트
-
새로고침의 마법
- 할 일을 추가하세요.
- 브라우저를 새로고침(F5) 하세요.
- 그대로 남아 있나요? (성공! 🎉)
- 22편에서는 사라졌었죠? 이제 영구 저장된 거예요.
-
기기 간 동기화
- 크롬 시크릿 탭을 켜거나, 다른 브라우저(사파리, 엣지)를 켜세요.
- 똑같이 로그인을 하세요.
- 아까 추가한 할 일이 보이나요? (성공! 🎉)
- 내 컴퓨터에 저장된 게 아니라, 저 멀리 Supabase 서버에 저장됐다는 뜻이에요.
-
삭제 확인
- 하나를 삭제하세요.
- 새로고침 해보세요.
- 진짜 사라졌나요? (성공! 🎉)
만약 3가지 다 통과했다면? 축하합니다. 여러분은 이제 **"풀스택(Full-stack) 서비스"**를 만든 거예요.
4. 자주 겪는 문제 해결 (Q&A)
막히는 부분이 있다면 여기를 체크해보세요.
Q. "로그인 했는데 자꾸 풀려요"
A. Supabase 설정에서
Site URL을 확인해보세요. Authentication → URL Configuration에http://localhost:3000이 등록되어 있어야 해요.
Q. "저장은 되는데 불러오기가 안 돼요" (또는 그 반대)
A. RLS(Row Level Security) 정책 때문일 확률이 99%입니다. 21편에서 RLS 정책 설정했었죠? 만약 안 했다면 AI한테 이렇게 시키세요.
"Supabase SQL 에디터에 넣을 코드를 짜줘.
todos테이블에 대해 로그인한 사용자는 자기 데이터만 CRUD 할 수 있게 RLS 정책을 설정해줘."
오늘의 핵심 정리
✅ 프론트엔드와 백엔드 연결: Supabase Client 라이브러리가 다리 역할을 해요.
✅ 인증(Auth): 복잡한 코딩 없이 Supabase Auth 도구를 쓰면 로그인이 뚝딱 돼요.
✅ CRUD:
- Create:
insert(추가) - Read:
select(조회) - Update:
update(수정) - Delete:
delete(삭제) ✅ 영구 저장: 이제 새로고침해도, 컴퓨터를 껐다 켜도 데이터가 살아있어요.
셀프체크
이 글을 완전히 이해했는지 확인해보세요.
□ "사용자 인증 기능을 구현해줘" 대신 AI에게 정확히 요청하려면? □ 데이터를 생성, 조회, 수정, 삭제하는 4가지 작업을 통틀어 뭐라고 부르나요? □ 프론트엔드에서 새로고침하면 데이터가 유지되는 이유는 어디에 저장했기 때문인가요?
정답 보기
- "Supabase Auth를 사용해서 로그인 기능을 구현해줘"
- CRUD (Create, Read, Update, Delete)
- DB (데이터베이스) 또는 백엔드 서버 (메모리가 아님)
다음 글 예고
이제 내 컴퓨터에서는 완벽하게 동작하는 '진짜 서비스'가 됐어요.
근데 친구한테 "이거 내가 만든 거야, 써봐" 하고 보여줄 수가 없죠?
주소가 localhost:3000이니까요. (이건 '내 집' 주소예요)
다음 시간에는 이 서비스를 **전 세계 누구나 접속할 수 있게 인터넷에 올리는 법(배포)**을 배울 거예요.
"클릭 몇 번으로 .vercel.app 멋진 주소 만들기", 기대해주세요!
이 시리즈 로드맵
PART 5: 첫 프로젝트 - 웹 서비스
[ 21편 ] 기획과 아키텍처 ✅
↓
[ 22편 ] 프론트엔드 구조 ✅
↓
[ 23편 ] 백엔드 연결 (지금 여기!)
↓
[ 24편 ] 배포하기
Supabase 연결이 잘 안 되나요? 에러 메시지를 댓글로 남겨주시면 도와드릴게요!