---
title: "🛡️ SAFEZONE — 멀티유저 데이터 분리·RLS 보안 기반 구축 (PACELINK 선행)"
notion_id: "36d22962086881dbad92c183c9697012"
notion_url: "https://app.notion.com/p/36d22962086881dbad92c183c9697012"
category: "security-planning"
parent: "달록 개발 현황"
updated: "2026-05-27"
priority: "High"
purpose: "v0.9 §5 작업 2의 정식 기획안 — 멀티유저 RLS 기반 구축 6-Step 워크플로우(진단·결정·적용·재테스트·차단테스트·문서화)"
read_when: ["DB·RLS·보안","제품로드맵"]
---

> 📌 **달록 v0.9 §5 작업 2의 정식 기획안.** 멀티유저 환경에서 사용자별 데이터를 안전하게 분리·보호하기 위한 RLS(Row Level Security) 기반 구축.
>
> **PACELINK(H-3 대형 기획) 본격 착수 전 반드시 완료되어야 하는 선행 작업**.
---
## 1. 프로젝트 개요
| 항목 | 내용 |
|---|---|
| 코드명 | **SAFEZONE** (안전구역 — 사용자별 데이터 분리) |
| 체크리스트 매핑 | 작업2-RLS-1~6 (체크리스트 K파트 끝, v0.9 §5 작업 2) |
| 성격 | 중형 세미프로젝트 |
| 후속 트랙 | 🧭 PACELINK 기획서 (H-3 대형 기획) |
| 예상 시간 | 약 3.5~6시간 (단일 작업일 내 완료 가능) |

---
## 2. 왜 별도 기획서인가
단일 RLS 정책 수정이 아니라 **멀티유저 모델 정립** + 6단계 RLS 검증 + 의사결정 + (필요 시) 마이그레이션 + OAuth 재테스트.
영향 범위:
- 현재 발견된 **이슈 11** (OAuth 계정 런타입 차단) 해소
- **이슈 2 잔존** (셀 모드 삭제 차단) 해소 가능성
- PACELINK·v0.9 클로즈베타·향후 모든 멀티유저 기능의 토대
---
## 3. 워크플로우 — 작업전개도
```mermaid
flowchart TD
    Prep[작업 전 준비<br/>Supabase 전체 CSV 백업<br/>OAuth 계정 2개+ 준비] --> S1[Step 1<br/>RLS 정책 진단<br/>30분~1시간]
    S1 --> S2[Step 2<br/>정책 결정 a vs b<br/>30분]
    S2 --> S3[Step 3<br/>정책 적용 SQL Editor<br/>1~2시간]
    S3 --> S4[Step 4<br/>OAuth 재테스트<br/>이슈 11 해소<br/>30분~1시간]
    S4 --> S5[Step 5<br/>타 사용자 차단 테스트<br/>30분~1시간]
    S5 --> S6[Step 6<br/>문서화 + 체크 완료<br/>30분]
    S6 --> Done[🧭 PACELINK Phase 1 착수 가능]
    style Prep fill:#fa3,stroke:#a60
    style S2 fill:#f93,stroke:#a30
    style S4 fill:#f55,stroke:#900,color:#fff
    style Done fill:#1d9,stroke:#080,color:#fff
```
ASCII 대체:
```plain text
[작업 전 준비]
   ├─ Supabase 전체 CSV 백업
   ├─ 테스트용 OAuth 계정 2개+ 준비 (ccy4848@gmail.com 등)
   └─ 본 페이지 펼친 상태로 진행

        ▼

[Step 1: RLS 정책 진단] ──── 30분~1시간
   ├─ Supabase Dashboard > Authentication > Policies
   ├─ 글로벌 테이블 4개 진단
   │     · run_type_configs
   │     · shoe_configs
   │     · exercise_configs
   │     · app_settings
   └─ 사용자 테이블 6개 진단
         · body_records / running_logs / strength_logs
         · strength_exercises / strength_sets / coach_notes

        ▼

[Step 2: 정책 결정 (a) vs (b)] ──── 30분
   ├─ (a) 글로벌 관리자 귀속 [권고]
   │     · SELECT 전체 허용
   │     · INSERT/UPDATE/DELETE 마스터만
   │     · 마이그레이션 0
   └─ (b) 사용자별 귀속
         · user_id 컬럼 추가
         · 분리 마이그레이션 필요

        ▼

[Step 3: 정책 적용 (SQL Editor)] ──── 1~2시간
   ├─ 글로벌 테이블 4개 정책 갱신
   └─ 사용자 테이블 6개 RLS 검증·보완

        ▼

[Step 4: OAuth 재테스트 (이슈 11 해소)] ──── 30분~1시간
   ├─ OAuth 계정 로그인
   ├─ 런타입 드롭다운 노출 확인
   ├─ 셀 모드 삭제 동작 확인 (이슈 2 잔존)
   └─ 마스터 ↔ OAuth 권한 비대칭 점검

        ▼

[Step 5: 다른 사용자 데이터 차단 테스트] ──── 30분~1시간
   └─ 2계정 교차 테스트 (서로 데이터 안 보이는지)

        ▼

[Step 6: 문서화 + 체크 완료] ──── 30분
   ├─ 본 기획서에 결과 보강
   ├─ 체크리스트 작업2-RLS-1~6 모두 체크
   └─ v0.9 충족기준 §5 작업 2 완료 표시

        ▼

[SAFEZONE 완료 → 🧭 PACELINK Phase 1 착수 가능]
```
---
## 4. Step별 상세
### Step 1: RLS 정책 진단 (30분~1시간)
**대상 테이블 (10개):**
- 글로벌: `run_type_configs` / `shoe_configs` / `exercise_configs` / `app_settings`
- 사용자: `body_records` / `running_logs` / `strength_logs` / `strength_exercises` / `strength_sets` / `coach_notes`
**확인 항목:**
- 각 테이블 RLS 활성화 여부
- 현재 정책 (SELECT/INSERT/UPDATE/DELETE)
- user_id 컬럼 존재 여부
**사용자가 할 일:**
- Supabase Dashboard 접속 (Auth > Policies)
- 각 테이블 정책 화면 스크린샷 캐처
- 본 페이지 또는 Claude Code에 전달
### Step 2: 정책 결정 (30분)
**(a) 글로벌 관리자 귀속 — 권고**
- 장점: 마이그레이션 0, 빠른 적용, 모든 사용자가 동일 종목/신발 목록 공유
- 단점: 사용자 커스텀 자유도 ↓
**(b) 사용자별 귀속**
- 장점: 사용자 커스텀 자유도 ↑
- 단점: 마이그레이션 + 기존 데이터 이관 부담, 사용자별 데이터 양 증가
**추천:** 클로즈베타 단계는 (a), 정식 출시 단계에서 (b)로 마이그레이션 검토
**사용자가 할 일:** (a)/(b) 결정 후 본 페이지에 기록
### Step 3: 정책 적용 (1~2시간)
SQL Editor에서 정책 갱신. (a) 패턴 예시:
```sql
ALTER TABLE run_type_configs ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "..." ON run_type_configs;
CREATE POLICY "Allow read all" ON run_type_configs
    FOR SELECT TO authenticated USING (true);
CREATE POLICY "Only master modify" ON run_type_configs
    FOR INSERT TO authenticated
    WITH CHECK (auth.jwt() ->> 'email' = '<마스터-이메일>');
-- UPDATE, DELETE 동일 패턴
```
**사용자가 할 일:**
- Supabase SQL Editor에서 Claude Code가 작성한 SQL 검토 후 실행
- 실행 결과 로그 본 페이지에 기록
### Step 4: OAuth 재테스트 (30분~1시간)
**시나리오:**
1. `ccy4848@gmail.com` (또는 다른 OAuth 계정) 로그인
2. `/log` 진입 → 런타입 드롭다운 노출 확인 (**이슈 11 해소**)
3. `/history` 진입 → 셀 모드 → 데이터 삭제 시도 → 정상 동작 (**이슈 2 잔존 해소**)
4. `/settings` 진입 → 종목/신발 추가 시도 → 정책에 맞게 동작 확인
**사용자가 할 일:** OAuth 계정 직접 로그인 후 시나리오 실행, 결과 스크린샷 첨부
### Step 5: 다른 사용자 데이터 차단 테스트 (30분~1시간)
**시나리오:**
- 마스터 계정 → 테스트 데이터 저장 → OAuth 계정 로그인 → 마스터 데이터 노출 여부 확인 (절대 보이면 안 됨)
- OAuth A → OAuth B 교차 검증
### Step 6: 문서화 (30분)
- 본 기획서에 Step 1~5 결과 추가
- 체크리스트 작업2-RLS-1~6 항목 모두 체크
- v0.9 충족기준 §5 작업 2 완료 표시 추가
- PACELINK 기획서에 "SAFEZONE 완료" 갱신
---
## 5. 총 예상 시간
| Step | 시간 |
|---|---|
| Step 1 | 30분~1시간 |
| Step 2 | 30분 |
| Step 3 | 1~2시간 |
| Step 4 | 30분~1시간 |
| Step 5 | 30분~1시간 |
| Step 6 | 30분 |
| **합계** | **약 3.5~6시간** (단일 작업일 내 완료 가능) |

---
## 6. 사용자가 해야 할 일 — 요약 체크리스트
- [ ] **Supabase 전체 CSV 백업** (작업 전 필수)
- [ ] Supabase Dashboard 접근 권한 보유
- [ ] 정책 결정 (a) vs (b) — 클로즈베타는 (a) 권고
- [ ] SQL 실행 결과 검토
- [ ] OAuth 계정으로 직접 테스트 (이미 보유 중인 `ccy4848@gmail.com` 사용 가능)
- [ ] 스크린샷·로그 본 페이지에 첨부
---
## 7. 리스크
| 리스크 | 영향 | 대응 |
|---|---|---|
| Step 3 SQL 적용 실수로 사용자 로그인 차단 | 매우 큼 | 작업 전 Supabase 전체 백업 필수 |
| (b) 결정 시 마이그레이션 실패 | 큼 | 사전 dry-run + 백업 |
| 정책 적용 후 기존 기능 일부 회귀 | 중간 | 핵심 라우트 5개 시각 검증 |

---
## 8. 완료 후 다음 단계
SAFEZONE 완료 → [🧭 PACELINK Phase 1] 착수 가능
---
## 9. 관련 페이지
- [v0.9 충족기준 §5 작업 2](#/doc/spec-01)
- [메인 체크리스트 K파트 작업2-RLS-1~6](#/doc/checklist-01)
- [🧭 PACELINK 기획서] (달록 PaceLog 하위, 동일 일자 생성)
- [💰 달록 수익화 시뮬레이션 보고서] (달록 PaceLog 하위, 동일 일자 생성)
- [핸드오프 26-05-26_1 §11-3](#/doc/handoff-13)
- 이슈 11 (OAuth 런타입 차단) / 이슈 2 잔존 (셀 모드 삭제 차단) — 본 작업으로 해소 예정
---
## 10. 갱신 이력
- 2026-05-27: 페이지 신규 생성 (SAFEZONE 코드명 부여, v0.9 §5 작업 2의 정식 기획서로 별도 분리)
