13회 · 앱에 데이터 연결: 웹과 앱이 같은 데이터를
Expo 앱에 웹앱과 같은 Supabase를 연결해 로그인과 모임 목록을 붙이고, 웹과 앱에서 같은 데이터가 보이는 것을 확인합니다.
“웹에서 만든 모임이 앱에도 바로 뜬다. 데이터베이스 하나, 화면 둘.”
학습 목표
- 앱이 데이터베이스와 통신하는 구조와 보안 원칙을 안다
- Expo 앱에 Supabase를 연결해 로그인과 모임 목록을 붙인다
- 웹과 앱에서 같은 데이터가 보이는 것을 확인한다
오늘 만드는 것: 웹과 데이터를 함께 쓰는 Expo 앱
실습 진도
—
실습 단계를 체크하면 표시돼요
오늘의 흐름
| 시간 | 내용 | 하는 일 |
|---|---|---|
| 0–10분 | 지난 시간 돌아보기 | 휴대폰에서 앱 열어 보기, 과제에서 나온 불편한 점 |
| 10–40분 | 앱과 데이터베이스 | 데이터베이스 하나·화면 둘, 공개 키와 보안 규칙, 로그인 유지 |
| 40–50분 | 요즘 업계에서는 | 백엔드 서비스(BaaS), Expo 공식 Supabase 안내, 앱 보안 사고 |
| 50–60분 | 시연 | 웹에서 모임을 만들면 앱에 바로 뜨는 장면 |
| 60–70분 | 쉬는 시간 | |
| 70–110분 | 실습 | 앱에 Supabase 연결 → 로그인 → 같은 데이터 확인 → 상태 화면 |
| 110–120분 | 정리와 퀴즈 | 보안 점검, 다음 시간(빌드와 출시) 안내 |
지난 시간 앱은 겉모습은 그럴듯했지만 가짜 데이터였습니다. 오늘은 7–9회에 만든 Supabase 데이터베이스를 앱에도 연결합니다. 그러면 웹에서 만든 모임이 앱에 뜨고, 앱에서 참석 신청한 것이 웹에도 보입니다.
데이터베이스 하나, 화면 둘
은행 계좌와 통장, 앱
내 돈은 은행(데이터베이스)에 있습니다. 같은 계좌를 은행 창구(웹앱)에서 봐도, 휴대폰 은행 앱(네이티브 앱)에서 봐도 잔액은 같습니다. 창구가 둘이라고 돈이 두 군데 있는 것이 아닙니다. 우리 모임도 마찬가지입니다. 모임과 참석 기록은 Supabase 한 곳에 있고, 웹앱과 앱은 그것을 보여 주는 두 개의 창구입니다.
┌──────────────┐
웹앱 ──────▶│ │
(Vercel) │ Supabase │ 모임, 참석 신청, 회원, 사진
│ (데이터베이스) │
앱 ────────▶│ │
(Expo) └──────────────┘이 구조의 장점은 분명합니다.
- 데이터를 두 번 관리하지 않습니다. 모임을 한 번 만들면 어디서나 보입니다.
- 보안 규칙도 한 곳에서 지킵니다. 8회에 만든 (행 수준 보안)가 웹과 앱 모두에 똑같이 적용됩니다.
- 회원 계정도 하나입니다. 웹에서 가입한 이메일로 앱에서도 로그인합니다.
앱에 넣어도 되는 키, 절대 넣으면 안 되는 키
8회에 배운 두 가지 키를 다시 떠올려 봅시다.
| 키 | 비유 | 웹앱에서 | 앱에서 |
|---|---|---|---|
| Supabase 주소 + | 건물 주소와 출입증 | 화면 코드에 들어가도 됨 | 앱에 들어가도 됨 |
| Supabase | 건물 마스터키 | 서버(환경변수)에만 | 절대 넣지 않음 |
| 데이터베이스 비밀번호 | 금고 비밀번호 | 넣지 않음 | 절대 넣지 않음 |
| Claude | 내 신용카드 | 서버(환경변수)에만 | 절대 넣지 않음 |
열쇠를 하나 누른 뒤, 둘 곳(브라우저 코드 / 서버 환경변수)을 누르세요.
왜 앱은 더 조심해야 할까요? 웹앱의 서버 코드는 Vercel 안에 숨어 있지만, 앱 설치 파일은 누구나 내려받아 열어 볼 수 있기 때문입니다. 앱 안에 넣은 값은 모두 공개된 것으로 생각해야 합니다.
Expo의 공식 Supabase 안내도 같은 이야기를 합니다. Supabase 주소와 공개 키는 원래 공개되는 값이라 보안은 RLS에 달려 있으니 앱이 쓰는 모든 테이블에 RLS를 켜고 규칙을 만들라고, 그리고 비밀 키는 RLS를 건너뛰어 모든 데이터에 접근하므로 앱에 절대 넣지 말라고 강조합니다 (Expo: Using Supabase).
AI 기능은 앱에서 어떻게?
10회에 만든 AI 요약 기능은 Claude API 키가 필요합니다. 이 키는 앱에 넣을 수 없으니, 앱은 웹앱의 서버(Vercel)에 "요약해 줘"라고 부탁하고, 서버가 키를 써서 Claude를 부르는 구조로 만듭니다. 오늘은 데이터 연결에 집중하고, AI 기능은 선택 과제로 남겨 둡니다.
로그인이 유지되는 앱
휴대폰 앱은 껐다 켤 때마다 다시 로그인하라고 하면 아무도 쓰지 않습니다. 그래서 로그인 정보(세션)를 휴대폰 안에 안전하게 저장해 두었다가 다시 켰을 때 꺼내 씁니다.
놀이공원 손목 밴드
입구에서 표를 확인받으면(로그인) 손목 밴드(세션)를 채워 줍니다. 밴드가 있으면 놀이기구마다 표를 다시 보여 줄 필요가 없습니다. 밴드는 시간이 지나면 새것으로 바꿔 줍니다(자동 갱신). 앱도 휴대폰 안에 이 밴드를 보관해 두는 것입니다.
Expo 공식 안내는 Supabase 로그인 정보를 휴대폰 안의 저장소(expo-sqlite)에 보관하고, 앱이 화면에 나와 있을 때만 로그인 정보를 자동으로 새로 고치도록 설정하는 방법을 보여 줍니다. 이런 세부 설정은 Claude Code가 공식 안내대로 해 줍니다. 우리는 **"앱을 껐다 켜도 로그인이 유지되는지"**를 확인하면 됩니다.
데이터를 가져오는 앱의 네 가지 상태
데이터베이스에서 모임을 가져오는 화면은 늘 네 가지 상태 중 하나입니다. 가짜 데이터일 때는 신경 쓸 일이 없었지만, 이제는 모두 챙겨야 합니다.
| 상태 | 언제 | 화면에 보여 줄 것 |
|---|---|---|
| 불러오는 중 | 데이터가 오는 중 | 빙글빙글 표시나 회색 빈 카드 |
| 비어 있음 | 모임이 하나도 없을 때 | "아직 모임이 없어요" + 만들기 안내 |
| 에러 | 서버 문제, 권한 문제 | "불러오지 못했어요" + 다시 시도 버튼 |
| 인터넷 끊김 | 지하철, 엘리베이터 | "인터넷 연결을 확인해 주세요" |
식당 주문
주문하자마자 음식이 나오지는 않습니다. 좋은 식당은 "조리 중입니다"(로딩), "오늘은 그 메뉴가 다 떨어졌어요"(비어 있음), "주방에 문제가 생겨 다시 주문해 주세요"(에러)를 손님에게 알려 줍니다. 아무 말 없이 빈 접시만 내오는 식당에는 다시 가지 않습니다.
자세히새로 고침과 실시간 반영펼치기
웹에서 모임을 만들었을 때 앱에 바로 나타나게 하는 방법은 두 가지입니다.
- 당겨서 새로 고침: 목록을 아래로 끌어당기면 다시 불러옵니다. 휴대폰 앱에서 가장 익숙한 방식이고 만들기도 쉽습니다.
- 실시간 반영: Supabase의 실시간(Realtime) 기능을 쓰면 데이터가 바뀌는 순간 화면이 저절로 바뀝니다. 채팅처럼 즉시성이 중요할 때 씁니다.
우리 모임처럼 일정이 하루에 몇 번 바뀌는 서비스는 당겨서 새로 고침으로 충분합니다. 기능은 필요할 때 더하는 것이 좋습니다.
요즘 업계에서는
서버를 직접 만들지 않는 시대: BaaS
예전에는 앱을 만들려면 데이터를 저장하고 로그인을 처리하는 서버를 직접 만들어야 했습니다. 요즘은 Supabase 같은 서비스가 데이터베이스, 로그인, 파일 저장, 보안 규칙을 한꺼번에 제공합니다. 이런 서비스를 BaaS(Backend as a Service, 서비스로 받는 백엔드)라고 부릅니다. 작은 팀이나 혼자 만드는 사람도 웹과 앱을 함께 운영할 수 있게 된 큰 이유입니다.
Expo는 공식 문서에 Supabase 연결 안내를 따로 두고 있고, eas integrations:supabase:connect라는 명령 한 줄로 필요한 부품 설치와 주소·공개 키 설정을 해 주는 방법도 소개합니다 (Expo: Using Supabase). 그만큼 Expo + Supabase가 흔한 조합이 됐다는 뜻입니다.
빠르게 만들수록 보안 점검은 더 중요해졌습니다
AI로 빠르게 만든 앱에서 보안 문제가 드러난 사례가 실제로 보고됐습니다. AI 앱 빌더 Lovable로 만든 공개 앱 1,645개를 조사했더니 170개에서 누구나 개인 데이터에 접근할 수 있는 취약점이 발견됐다는 조사가 있었습니다 (위키백과: Vibe coding). 대부분 보안 규칙(RLS)이 없거나 허술한 경우였습니다.
교훈은 단순합니다. AI에게 만들게 했으면, 점검도 AI에게 시키고, 확인은 사람이 직접 합니다. 오늘 실습 마지막에 보안 점검을 꼭 하는 이유입니다.
시연
강사가 Expo 앱에 Supabase를 연결합니다. 웹앱과 같은 Supabase 프로젝트의 주소와 공개 키만 앱에 넣는 장면을 보여 줍니다. 노트북 브라우저의 웹앱에서 "11월 모임 · 『작은 것들의 신』"을 새로 만들고, 휴대폰 앱에서 목록을 당겨 새로 고침해 바로 나타나는 것을 확인합니다. 반대로 앱에서 참석 신청을 하면 웹앱의 남은 자리가 줄어드는 것도 보여 줍니다. 마지막으로 비행기 모드를 켜서 인터넷 끊김 화면을 확인합니다.
실습
실습 13-1 · 앱에 Supabase 연결하기
약 15분웹앱과 같은 Supabase 프로젝트를 쓰고, 공개 키만 앱에 넣습니다.
- Supabase 대시보드에서 7회에 만든 우리 모임 프로젝트를 엽니다.Project Settings → API Keys(또는 Connect 버튼)에서 프로젝트 주소(URL)와 공개 키(publishable 또는 anon)를 확인합니다.비밀 키(secret 또는 service_role)는 오늘 쓰지 않습니다. 복사하지도 마세요.
메뉴 이름은 Supabase 화면이 바뀌면서 조금씩 달라질 수 있습니다. 찾기 어려우면 웹앱 폴더의
.env.local파일에 이미 적혀 있는 주소와 공개 키를 Claude Code에게 찾아 달라고 해도 됩니다. Claude Code에서 12회에 만든
moim-app폴더를 엽니다.PROMPT앱에 Supabase 연결Expo 앱에 Supabase를 연결해줘. 웹앱과 같은 프로젝트를 쓰고, 공개 키만 앱에 넣어줘. 로그인 상태는 앱을 껐다 켜도 유지되게, 모임 목록은 Supabase에서 읽어오게 해줘.
주소와 공개 키는 Claude Code가 만든
.env파일에 직접 붙여 넣으세요. 채팅창에 붙여 넣는 것보다 안전한 습관입니다. Expo 앱에서는 앱에 들어가도 되는 값만EXPO_PUBLIC_으로 시작하는 이름을 씁니다.이렇게 되면 성공✓ @supabase/supabase-js, expo-sqlite 설치✓ lib/supabase.ts (주소와 공개 키는 .env에서 읽음)✓ 모임 목록을 Supabase meetups 테이블에서 불러옴> Expo Go에서 앱을 다시 열어 보세요. 웹에 있는 모임이 보여야 합니다.막혔을 때
실습 13-2 · 로그인 붙이기
약 12분- PROMPT앱 로그인 화면 플랜 모드 권장
Expo 앱에 이메일 로그인 화면을 만들어줘. 웹앱과 같은 Supabase 계정으로 로그인되게, 로그인하지 않았으면 로그인 화면이 먼저 나오게, 내 정보 탭에는 로그아웃 버튼을. 먼저 계획을 보여줘.
이렇게 되면 성공✓ 로그인하지 않으면 로그인 화면이 먼저 나옴✓ 웹앱에서 가입한 이메일로 로그인 성공✓ 내 정보 탭에 내 이메일과 로그아웃 버튼로그인할 때 쓰는 이메일과 비밀번호는 여러분이 휴대폰에서 직접 입력합니다. Claude Code에게 비밀번호를 알려 주지 마세요.
Expo Go를 완전히 닫았다가(최근 앱 목록에서 위로 밀어 닫기) 다시 열어 우리 모임 앱을 엽니다. 로그인 화면이 다시 나오지 않으면 성공입니다.
실습 13-3 · 웹과 앱, 같은 데이터 확인
약 10분두 창구에서 같은 계좌가 보이는지 직접 확인합니다.
- PROMPT웹과 앱 데이터 확인
웹에서 만든 모임이 앱에도 보이는지, 앱에서 참석 신청한 것이 웹에도 반영되는지 확인하는 순서를 알려줘.
- 노트북 브라우저에서 웹앱(배포 주소)에 로그인하고 새 모임을 하나 만듭니다. 예: "11월 모임 · 동네 북카페 · 정원 8명"휴대폰 앱에서 목록을 새로 고칩니다. 방금 만든 모임이 보이나요?앱에서 그 모임에 참석 신청을 합니다.웹앱을 새로 고칩니다. 남은 자리가 하나 줄었나요?이렇게 되면 성공웹에서 만든 모임 → 앱 목록에 보임앱에서 참석 신청 → 웹의 남은 자리 7명막혔을 때
실습 13-4 · 상태 화면과 보안 점검
약 8분- PROMPT로딩·빈 목록·에러 화면 챙기기
모임 목록 화면에 네 가지 상태를 모두 만들어줘. 불러오는 중(로딩), 모임이 하나도 없을 때(빈 화면), 에러가 났을 때(다시 시도 버튼), 인터넷이 끊겼을 때. 각 상태를 내가 직접 시험해 볼 방법도 알려줘.
비행기 모드를 켜고 목록을 새로 고쳐 확인한 뒤, 꼭 다시 끄세요.
- PROMPT앱에 비밀 키가 없는지 점검
이 Expo 앱 코드와 설정 파일 전체에서 Supabase 비밀 키(secret, service_role)나 데이터베이스 비밀번호, Claude API 키가 들어간 곳이 있는지 찾아줘. 앱에 들어가도 되는 것은 Supabase 주소와 공개 키뿐이야. 결과를 표로 보여줘.
이렇게 되면 성공| 찾은 값 | 위치 | 판정 || Supabase 주소 | .env (EXPO_PUBLIC_) | 괜찮음 || Supabase 공개 키 | .env (EXPO_PUBLIC_) | 괜찮음 || 비밀 키 / DB 비밀번호 / Claude API 키 | 없음 | 괜찮음 |마지막으로
.env파일이 GitHub에 올라가지 않도록 .gitignore에 들어 있는지도 확인하고 커밋합니다.PROMPT보안 점검이 프로젝트의 보안을 점검해줘. 키가 코드에 노출돼 있거나, 보안 규칙(RLS) 없이 누구나 쓸 수 있는 테이블, 앱 안에 들어간 비밀 키가 있는지 확인해서 목록으로 보여줘.
사람이 직접 하는 테스트
약 8분AI가 '다 됐어요'라고 해도 확인은 사람의 몫입니다.
- PROMPT테스트 체크리스트 받기
지금까지 만든 기능을 사람이 직접 확인할 수 있는 테스트 체크리스트를 만들어줘. 로그인 안 한 사람, 로그인한 사람, 다른 사람 입장에서 각각 해 볼 것을 나눠서.
옆 사람과 휴대폰을 바꿔 서로의 앱으로 체크리스트를 해 보세요. 다른 사람 계정으로 내 모임을 고칠 수 없는지도 꼭 확인합니다.
정리
핵심 정리
- 1데이터베이스는 하나, 화면은 둘. 웹앱과 앱이 같은 Supabase를 쓰면 데이터·회원·보안 규칙을 한 곳에서 관리한다.
- 2앱에 넣어도 되는 것은 Supabase 주소와 공개 키뿐. 앱 설치 파일은 누구나 열어 볼 수 있다.
- 3공개 키가 공개돼도 안전한 이유는 RLS다. 앱이 쓰는 모든 테이블에 보안 규칙을 켠다.
- 4로그인 정보는 휴대폰 안에 보관해 껐다 켜도 유지되게 한다.
- 5데이터를 가져오는 화면은 로딩·비어 있음·에러·인터넷 끊김 네 가지 상태를 챙긴다.
다음 시간에는 Expo Go 없이도 열리는 진짜 설치 파일을 만들고, 스토어에 올리려면 무엇이 필요한지 준비합니다.
복습
Q1.웹앱과 Expo 앱이 같은 Supabase를 쓸 때의 장점이 아닌 것은?
Q2.Expo 앱 안에 넣어도 되는 값은?
Q3.앱에서 AI 요약 기능을 쓰려면 Claude API 키를 앱 코드에 넣어야 한다.
Q4.앱을 껐다 켜도 다시 로그인하지 않아도 되는 이유는?
Q5.데이터를 가져오는 화면이 챙겨야 할 네 가지 상태에 들어가지 않는 것은?
Q6.앱에서 참석 신청이 보안 규칙에 막히면, 보안 규칙(RLS)을 꺼서 해결하는 것이 가장 좋다.
과제
과제 · 웹과 앱, 같은 데이터 인증
가족이나 친구에게 웹앱에서 가입하게 하고, 그 계정으로 내 휴대폰 앱에 로그인해 참석 신청을 해 보게 하세요. 다른 사람이 만든 모임은 고칠 수 없는지도 함께 확인합니다.