mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 06:46:25 +00:00
✨ 주요 기능 - Azure 기반 물리아키텍처 설계 (개발환경/운영환경) - 7개 마이크로서비스 물리 구조 설계 - 네트워크 아키텍처 다이어그램 작성 (Mermaid) - 환경별 비교 분석 및 마스터 인덱스 문서 📁 생성 파일 - design/backend/physical/physical-architecture.md (마스터) - design/backend/physical/physical-architecture-dev.md (개발환경) - design/backend/physical/physical-architecture-prod.md (운영환경) - design/backend/physical/*.mmd (4개 Mermaid 다이어그램) 🎯 핵심 성과 - 비용 최적화: 개발환경 월 $143, 운영환경 월 $2,860 - 확장성: 개발환경 100명 → 운영환경 10,000명 (100배) - 가용성: 개발환경 95% → 운영환경 99.9% - 보안: 다층 보안 아키텍처 (L1~L4) 🛠️ 기술 스택 - Azure Kubernetes Service (AKS) - Azure Database for PostgreSQL Flexible - Azure Cache for Redis Premium - Azure Service Bus Premium - Application Gateway + WAF 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
351 lines
8.8 KiB
Markdown
351 lines
8.8 KiB
Markdown
# User Service 데이터베이스 설계서
|
|
|
|
## 데이터 설계 요약
|
|
|
|
### 📋 설계 개요
|
|
- **서비스명**: user-service
|
|
- **데이터베이스**: PostgreSQL 16
|
|
- **캐시 DB**: Redis 7
|
|
- **테이블 수**: 2개 (users, stores)
|
|
- **인덱스 수**: 5개
|
|
- **설계 원칙**: 마이크로서비스 데이터 독립성 원칙 준수
|
|
|
|
### 🎯 핵심 특징
|
|
- **독립 데이터베이스**: user-service만의 독립적인 스키마
|
|
- **1:1 Entity 매핑**: 클래스 설계서의 User, Store Entity와 정확히 일치
|
|
- **JWT 기반 인증**: Redis를 활용한 세션 및 Blacklist 관리
|
|
- **성능 최적화**: 조회 패턴 기반 인덱스 설계
|
|
- **보안**: 비밀번호 bcrypt 암호화, 민감 정보 암호화 저장
|
|
|
|
---
|
|
|
|
## 1. 테이블 설계
|
|
|
|
### 1.1 users 테이블
|
|
|
|
**목적**: 사용자(소상공인) 정보 관리
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|---------|------|
|
|
| id | UUID | PK | 사용자 고유 식별자 |
|
|
| name | VARCHAR(100) | NOT NULL | 사용자 이름 |
|
|
| phone_number | VARCHAR(20) | NOT NULL, UNIQUE | 전화번호 (중복 검증) |
|
|
| email | VARCHAR(255) | NOT NULL, UNIQUE | 이메일 (로그인 ID) |
|
|
| password_hash | VARCHAR(255) | NOT NULL | bcrypt 암호화된 비밀번호 |
|
|
| role | VARCHAR(20) | NOT NULL | 사용자 역할 (OWNER, ADMIN) |
|
|
| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 계정 상태 |
|
|
| last_login_at | TIMESTAMP | NULL | 최종 로그인 시각 |
|
|
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 생성 시각 |
|
|
| updated_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 수정 시각 |
|
|
|
|
**제약조건**:
|
|
- PRIMARY KEY: id
|
|
- UNIQUE: email, phone_number
|
|
- CHECK: role IN ('OWNER', 'ADMIN')
|
|
- CHECK: status IN ('ACTIVE', 'INACTIVE', 'LOCKED', 'WITHDRAWN')
|
|
|
|
**인덱스**:
|
|
- `idx_users_email`: 로그인 조회 최적화
|
|
- `idx_users_phone_number`: 전화번호 중복 검증 최적화
|
|
- `idx_users_status`: 활성 사용자 필터링 최적화
|
|
|
|
---
|
|
|
|
### 1.2 stores 테이블
|
|
|
|
**목적**: 가게(매장) 정보 관리
|
|
|
|
| 컬럼명 | 타입 | 제약조건 | 설명 |
|
|
|--------|------|---------|------|
|
|
| id | UUID | PK | 가게 고유 식별자 |
|
|
| user_id | UUID | NOT NULL, UNIQUE, FK | 사용자 ID (1:1 관계) |
|
|
| name | VARCHAR(200) | NOT NULL | 가게 이름 |
|
|
| industry | VARCHAR(100) | NOT NULL | 업종 |
|
|
| address | VARCHAR(500) | NOT NULL | 주소 |
|
|
| business_hours | TEXT | NULL | 영업시간 |
|
|
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 생성 시각 |
|
|
| updated_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 수정 시각 |
|
|
|
|
**제약조건**:
|
|
- PRIMARY KEY: id
|
|
- FOREIGN KEY: user_id REFERENCES users(id) ON DELETE CASCADE
|
|
- UNIQUE: user_id (1:1 관계 보장)
|
|
|
|
**인덱스**:
|
|
- `idx_stores_user_id`: User-Store 조인 최적화
|
|
|
|
---
|
|
|
|
## 2. 관계 설계
|
|
|
|
### 2.1 User ↔ Store (1:1 양방향)
|
|
|
|
```
|
|
users(1) ---- (1)stores
|
|
└─ user_id FK
|
|
```
|
|
|
|
**관계 특성**:
|
|
- **Type**: One-to-One Bidirectional
|
|
- **Owner**: Store (FK를 소유)
|
|
- **Cascade**: ALL (User 삭제 시 Store도 삭제)
|
|
- **Lazy Loading**: User 조회 시 Store는 지연 로딩
|
|
|
|
**비즈니스 규칙**:
|
|
- 하나의 User는 최대 하나의 Store만 소유
|
|
- Store는 반드시 User에 속해야 함 (NOT NULL FK)
|
|
- User 삭제 시 Store도 함께 삭제 (CASCADE)
|
|
|
|
---
|
|
|
|
## 3. 인덱스 설계
|
|
|
|
### 3.1 인덱스 목록
|
|
|
|
| 인덱스명 | 테이블 | 컬럼 | 목적 | 유형 |
|
|
|---------|--------|------|------|------|
|
|
| idx_users_email | users | email | 로그인 조회 | UNIQUE |
|
|
| idx_users_phone_number | users | phone_number | 중복 검증 | UNIQUE |
|
|
| idx_users_status | users | status | 활성 사용자 필터링 | B-tree |
|
|
| idx_stores_user_id | stores | user_id | User-Store 조인 | UNIQUE |
|
|
|
|
### 3.2 조회 패턴 분석
|
|
|
|
**빈번한 조회 패턴**:
|
|
1. **로그인**: `SELECT * FROM users WHERE email = ?` → idx_users_email
|
|
2. **중복 검증**: `SELECT COUNT(*) FROM users WHERE phone_number = ?` → idx_users_phone_number
|
|
3. **프로필 조회**: `SELECT u.*, s.* FROM users u LEFT JOIN stores s ON u.id = s.user_id WHERE u.id = ?`
|
|
4. **활성 사용자**: `SELECT * FROM users WHERE status = 'ACTIVE'` → idx_users_status
|
|
|
|
---
|
|
|
|
## 4. Redis 캐시 설계
|
|
|
|
### 4.1 JWT 세션 관리
|
|
|
|
**키 패턴**: `session:{token}`
|
|
|
|
**데이터 구조**:
|
|
```json
|
|
{
|
|
"userId": "UUID",
|
|
"role": "OWNER|ADMIN",
|
|
"email": "user@example.com",
|
|
"expiresAt": "timestamp"
|
|
}
|
|
```
|
|
|
|
**TTL**: JWT 만료 시간과 동일 (예: 7일)
|
|
|
|
**목적**:
|
|
- JWT 토큰 검증 시 DB 조회 방지
|
|
- 빠른 인증 처리
|
|
- 로그아웃 시 세션 삭제
|
|
|
|
---
|
|
|
|
### 4.2 JWT Blacklist
|
|
|
|
**키 패턴**: `blacklist:{token}`
|
|
|
|
**데이터 구조**:
|
|
```json
|
|
{
|
|
"userId": "UUID",
|
|
"logoutAt": "timestamp"
|
|
}
|
|
```
|
|
|
|
**TTL**: 토큰 원래 만료 시간까지
|
|
|
|
**목적**:
|
|
- 로그아웃된 토큰 재사용 방지
|
|
- 유효한 토큰이지만 무효화된 토큰 관리
|
|
- 보안 강화
|
|
|
|
---
|
|
|
|
## 5. 데이터 무결성 및 보안
|
|
|
|
### 5.1 제약조건
|
|
|
|
**NOT NULL 제약**:
|
|
- 필수 필드: name, email, password_hash, role, status
|
|
- Store 필수 필드: user_id, name, industry, address
|
|
|
|
**UNIQUE 제약**:
|
|
- email: 로그인 ID 중복 방지
|
|
- phone_number: 전화번호 중복 방지
|
|
- stores.user_id: 1:1 관계 보장
|
|
|
|
**CHECK 제약**:
|
|
- role: OWNER, ADMIN만 허용
|
|
- status: ACTIVE, INACTIVE, LOCKED, WITHDRAWN만 허용
|
|
|
|
**FOREIGN KEY 제약**:
|
|
- stores.user_id → users.id (ON DELETE CASCADE)
|
|
|
|
### 5.2 보안
|
|
|
|
**비밀번호 보안**:
|
|
- bcrypt 알고리즘 사용 (cost factor 12)
|
|
- password_hash 컬럼에 저장
|
|
- 원본 비밀번호는 저장하지 않음
|
|
|
|
**민감 정보 보호**:
|
|
- 전화번호, 이메일: 암호화 고려 (필요시)
|
|
- 주소: 개인정보이므로 접근 제어
|
|
|
|
---
|
|
|
|
## 6. 성능 최적화 전략
|
|
|
|
### 6.1 인덱스 전략
|
|
|
|
**단일 컬럼 인덱스**:
|
|
- email, phone_number: UNIQUE 인덱스로 조회 및 중복 검증
|
|
- status: 활성 사용자 필터링
|
|
|
|
**복합 인덱스 검토**:
|
|
- 현재는 불필요 (단순 조회 패턴)
|
|
- 추후 복잡한 검색 조건 추가 시 고려
|
|
|
|
### 6.2 캐시 전략
|
|
|
|
**Redis 활용**:
|
|
- JWT 세션: DB 조회 없이 인증 처리
|
|
- Blacklist: 로그아웃 토큰 빠른 검증
|
|
|
|
**캐시 갱신**:
|
|
- 프로필 수정 시 세션 캐시 갱신
|
|
- 비밀번호 변경 시 모든 세션 무효화
|
|
|
|
### 6.3 쿼리 최적화
|
|
|
|
**N+1 문제 방지**:
|
|
- User 조회 시 Store LEFT JOIN으로 한 번에 조회
|
|
- JPA: `@OneToOne(fetch = FetchType.LAZY)` + 필요시 fetch join
|
|
|
|
**배치 처리**:
|
|
- 대량 사용자 조회 시 IN 절 활용
|
|
- 페이징 처리: LIMIT/OFFSET 또는 커서 기반
|
|
|
|
---
|
|
|
|
## 7. 확장성 고려사항
|
|
|
|
### 7.1 수직 확장 (Scale-Up)
|
|
|
|
**현재 설계로 충분**:
|
|
- 예상 사용자: 10만 명 이하
|
|
- 단순한 스키마 구조
|
|
- 효율적인 인덱스
|
|
|
|
### 7.2 수평 확장 (Scale-Out)
|
|
|
|
**샤딩 전략 (필요 시)**:
|
|
- 샤딩 키: user_id (UUID 기반)
|
|
- 읽기 복제본: 조회 성능 향상
|
|
- Redis Cluster: 세션 분산 저장
|
|
|
|
### 7.3 데이터 증가 대응
|
|
|
|
**파티셔닝**:
|
|
- 현재는 불필요
|
|
- 수백만 사용자 이상 시 status별 파티셔닝 고려
|
|
|
|
**아카이빙**:
|
|
- WITHDRAWN 사용자 데이터 아카이빙
|
|
- 1년 이상 비활성 사용자 별도 테이블 이관
|
|
|
|
---
|
|
|
|
## 8. 백업 및 복구 전략
|
|
|
|
### 8.1 백업
|
|
|
|
**PostgreSQL**:
|
|
- 일일 전체 백업 (pg_dump)
|
|
- WAL 아카이빙 (Point-in-Time Recovery)
|
|
- 보관 기간: 30일
|
|
|
|
**Redis**:
|
|
- RDB 스냅샷: 1시간마다
|
|
- AOF 로그: appendfsync everysec
|
|
- 보관 기간: 7일
|
|
|
|
### 8.2 복구
|
|
|
|
**재해 복구 목표**:
|
|
- RPO (Recovery Point Objective): 1시간
|
|
- RTO (Recovery Time Objective): 30분
|
|
|
|
**복구 절차**:
|
|
1. PostgreSQL: WAL 기반 특정 시점 복구
|
|
2. Redis: RDB + AOF 조합 복구
|
|
3. 세션 재생성: 사용자 재로그인
|
|
|
|
---
|
|
|
|
## 9. 모니터링 및 알림
|
|
|
|
### 9.1 모니터링 항목
|
|
|
|
**데이터베이스**:
|
|
- Connection Pool 사용률
|
|
- Slow Query (1초 이상)
|
|
- 인덱스 사용률
|
|
- 테이블 크기 증가율
|
|
|
|
**캐시**:
|
|
- Redis 메모리 사용률
|
|
- 캐시 히트율
|
|
- Eviction 발생 빈도
|
|
|
|
### 9.2 알림 임계값
|
|
|
|
**Critical**:
|
|
- Connection Pool 사용률 > 90%
|
|
- Slow Query > 10건/분
|
|
- Redis 메모리 사용률 > 90%
|
|
|
|
**Warning**:
|
|
- Connection Pool 사용률 > 70%
|
|
- Slow Query > 5건/분
|
|
- 캐시 히트율 < 80%
|
|
|
|
---
|
|
|
|
## 10. 마이그레이션 및 버전 관리
|
|
|
|
### 10.1 스키마 버전 관리
|
|
|
|
**도구**: Flyway 또는 Liquibase
|
|
|
|
**마이그레이션 파일**:
|
|
- `V1__create_users_table.sql`
|
|
- `V2__create_stores_table.sql`
|
|
- `V3__add_indexes.sql`
|
|
|
|
### 10.2 무중단 마이그레이션
|
|
|
|
**컬럼 추가**:
|
|
1. 새 컬럼 추가 (NULL 허용)
|
|
2. 애플리케이션 배포
|
|
3. 데이터 마이그레이션
|
|
4. NOT NULL 제약 추가
|
|
|
|
**컬럼 삭제**:
|
|
1. 애플리케이션에서 사용 중단
|
|
2. 배포 및 검증
|
|
3. 컬럼 삭제
|
|
|
|
---
|
|
|
|
## 11. 참고 자료
|
|
|
|
- **클래스 설계서**: design/backend/class/user-service.puml
|
|
- **공통 컴포넌트**: design/backend/class/common-base.puml
|
|
- **ERD**: design/backend/database/user-service-erd.puml
|
|
- **스키마**: design/backend/database/user-service-schema.psql
|