mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 17:26:23 +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>
364 lines
11 KiB
Markdown
364 lines
11 KiB
Markdown
# Distribution Service 데이터베이스 설계서
|
|
|
|
## 📋 데이터설계 요약
|
|
|
|
### 설계 개요
|
|
- **서비스명**: Distribution Service
|
|
- **아키텍처 패턴**: Layered Architecture
|
|
- **데이터베이스**: PostgreSQL (배포 상태 영구 저장), Redis (실시간 모니터링)
|
|
- **설계 일시**: 2025-10-29
|
|
- **설계자**: Backend Developer (최수연 "아키텍처")
|
|
|
|
### 데이터 특성
|
|
- **배포 상태 관리**: 이벤트별 다중 채널 배포 상태 추적
|
|
- **채널 독립성**: 6개 채널(TV, CALL, SNS)별 독립적 상태 관리
|
|
- **실시간 모니터링**: Redis 캐시를 통한 배포 진행 상태 실시간 조회
|
|
- **성과 추적**: 채널별 도달률(estimatedViews), 완료 시간, 재시도 횟수 추적
|
|
- **에러 관리**: 채널별 에러 메시지, 재시도 정보 저장
|
|
|
|
### 주요 테이블
|
|
1. **distribution_status**: 배포 전체 상태 관리 (이벤트 ID, 전체 상태, 시작/완료 시간)
|
|
2. **channel_status**: 채널별 세부 배포 상태 (채널 타입, 진행률, 배포 ID, 도달률, 에러 정보)
|
|
|
|
### 캐시 설계
|
|
- **event:{eventId}:distribution**: 배포 상태 실시간 조회 (TTL: 1시간)
|
|
- **distribution:channel:{eventId}:{channel}**: 채널별 상태 캐시 (TTL: 30분)
|
|
|
|
---
|
|
|
|
## 1. 데이터베이스 스키마 설계
|
|
|
|
### 1.1 PostgreSQL 테이블 설계
|
|
|
|
#### 1.1.1 distribution_status (배포 상태 테이블)
|
|
|
|
**테이블 목적**: 이벤트별 배포 전체 상태 관리
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | BIGSERIAL | NO | - | 배포 상태 ID (PK) |
|
|
| event_id | VARCHAR(36) | NO | - | 이벤트 ID (UUID) |
|
|
| overall_status | VARCHAR(20) | NO | - | 전체 배포 상태 (IN_PROGRESS, COMPLETED, FAILED, PARTIAL_SUCCESS) |
|
|
| started_at | TIMESTAMP | NO | - | 배포 시작 시간 |
|
|
| completed_at | TIMESTAMP | YES | NULL | 배포 완료 시간 |
|
|
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 생성 시간 |
|
|
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 수정 시간 |
|
|
|
|
**제약 조건**:
|
|
- PRIMARY KEY: id
|
|
- UNIQUE KEY: event_id (이벤트당 하나의 배포 상태만 존재)
|
|
- INDEX: event_id (조회 성능 최적화)
|
|
- CHECK: overall_status IN ('IN_PROGRESS', 'COMPLETED', 'FAILED', 'PARTIAL_SUCCESS')
|
|
|
|
#### 1.1.2 channel_status (채널 배포 상태 테이블)
|
|
|
|
**테이블 목적**: 채널별 세부 배포 상태 및 성과 추적
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | BIGSERIAL | NO | - | 채널 상태 ID (PK) |
|
|
| distribution_status_id | BIGINT | NO | - | 배포 상태 ID (FK) |
|
|
| channel | VARCHAR(20) | NO | - | 채널 타입 (URIDONGNETV, RINGOBIZ, GINITV, INSTAGRAM, NAVER, KAKAO) |
|
|
| status | VARCHAR(20) | NO | - | 채널 배포 상태 (PENDING, IN_PROGRESS, SUCCESS, FAILED) |
|
|
| progress | INTEGER | YES | 0 | 진행률 (0-100) |
|
|
| distribution_id | VARCHAR(100) | YES | NULL | 채널별 배포 ID (외부 시스템 ID) |
|
|
| estimated_views | INTEGER | YES | 0 | 예상 도달률 (조회수) |
|
|
| update_timestamp | TIMESTAMP | NO | CURRENT_TIMESTAMP | 상태 업데이트 시간 |
|
|
| event_id | VARCHAR(36) | NO | - | 이벤트 ID (조회 최적화용) |
|
|
| impression_schedule | TEXT | YES | NULL | 노출 일정 (JSON 배열) |
|
|
| post_url | VARCHAR(500) | YES | NULL | 게시물 URL |
|
|
| post_id | VARCHAR(100) | YES | NULL | 게시물 ID |
|
|
| message_id | VARCHAR(100) | YES | NULL | 메시지 ID (카카오톡) |
|
|
| completed_at | TIMESTAMP | YES | NULL | 채널 배포 완료 시간 |
|
|
| error_message | TEXT | YES | NULL | 에러 메시지 |
|
|
| retries | INTEGER | YES | 0 | 재시도 횟수 |
|
|
| last_retry_at | TIMESTAMP | YES | NULL | 마지막 재시도 시간 |
|
|
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 생성 시간 |
|
|
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 수정 시간 |
|
|
|
|
**제약 조건**:
|
|
- PRIMARY KEY: id
|
|
- FOREIGN KEY: distribution_status_id REFERENCES distribution_status(id) ON DELETE CASCADE
|
|
- UNIQUE KEY: (distribution_status_id, channel) - 배포당 채널별 하나의 상태만 존재
|
|
- INDEX: event_id (이벤트별 조회 최적화)
|
|
- INDEX: (event_id, channel) (채널별 조회 최적화)
|
|
- INDEX: status (상태별 조회 최적화)
|
|
- CHECK: channel IN ('URIDONGNETV', 'RINGOBIZ', 'GINITV', 'INSTAGRAM', 'NAVER', 'KAKAO')
|
|
- CHECK: status IN ('PENDING', 'IN_PROGRESS', 'SUCCESS', 'FAILED')
|
|
- CHECK: progress BETWEEN 0 AND 100
|
|
|
|
---
|
|
|
|
### 1.2 Redis 캐시 설계
|
|
|
|
#### 1.2.1 배포 상태 캐시
|
|
|
|
**키 패턴**: `event:{eventId}:distribution`
|
|
|
|
**데이터 구조**: Hash
|
|
```json
|
|
{
|
|
"eventId": "uuid",
|
|
"overallStatus": "IN_PROGRESS",
|
|
"startedAt": "2025-10-29T10:00:00",
|
|
"completedAt": null,
|
|
"successCount": 3,
|
|
"failureCount": 1,
|
|
"totalChannels": 6
|
|
}
|
|
```
|
|
|
|
**TTL**: 1시간 (3600초)
|
|
|
|
**사용 목적**:
|
|
- 배포 상태 실시간 조회 성능 최적화
|
|
- DB 부하 감소 (조회 빈도가 높은 데이터)
|
|
- 배포 진행 중 빠른 상태 업데이트
|
|
|
|
#### 1.2.2 채널별 상태 캐시
|
|
|
|
**키 패턴**: `distribution:channel:{eventId}:{channel}`
|
|
|
|
**데이터 구조**: Hash
|
|
```json
|
|
{
|
|
"channel": "INSTAGRAM",
|
|
"status": "IN_PROGRESS",
|
|
"progress": 75,
|
|
"distributionId": "ig_post_12345",
|
|
"estimatedViews": 5000,
|
|
"updateTimestamp": "2025-10-29T10:30:00",
|
|
"postUrl": "https://instagram.com/p/abc123",
|
|
"errorMessage": null
|
|
}
|
|
```
|
|
|
|
**TTL**: 30분 (1800초)
|
|
|
|
**사용 목적**:
|
|
- 채널별 배포 상태 실시간 모니터링
|
|
- 진행률 추적 및 업데이트
|
|
- 외부 API 호출 결과 임시 저장
|
|
|
|
---
|
|
|
|
## 2. Entity-Table 매핑
|
|
|
|
### 2.1 DistributionStatus Entity → distribution_status Table
|
|
|
|
| Entity 필드 | 테이블 컬럼 | 매핑 |
|
|
|-------------|-------------|------|
|
|
| id | id | 1:1 |
|
|
| eventId | event_id | 1:1 |
|
|
| overallStatus | overall_status | 1:1 |
|
|
| startedAt | started_at | 1:1 |
|
|
| completedAt | completed_at | 1:1 |
|
|
| channels | (관계) | 1:N → channel_status |
|
|
| createdAt | created_at | 1:1 (BaseTimeEntity) |
|
|
| updatedAt | updated_at | 1:1 (BaseTimeEntity) |
|
|
|
|
### 2.2 ChannelStatusEntity Entity → channel_status Table
|
|
|
|
| Entity 필드 | 테이블 컬럼 | 매핑 |
|
|
|-------------|-------------|------|
|
|
| id | id | 1:1 |
|
|
| distributionStatus | distribution_status_id | N:1 (FK) |
|
|
| channel | channel | 1:1 (Enum) |
|
|
| status | status | 1:1 |
|
|
| progress | progress | 1:1 |
|
|
| distributionId | distribution_id | 1:1 |
|
|
| estimatedViews | estimated_views | 1:1 |
|
|
| updateTimestamp | update_timestamp | 1:1 |
|
|
| eventId | event_id | 1:1 |
|
|
| impressionSchedule | impression_schedule | 1:1 (JSON String) |
|
|
| postUrl | post_url | 1:1 |
|
|
| postId | post_id | 1:1 |
|
|
| messageId | message_id | 1:1 |
|
|
| completedAt | completed_at | 1:1 |
|
|
| errorMessage | error_message | 1:1 |
|
|
| retries | retries | 1:1 |
|
|
| lastRetryAt | last_retry_at | 1:1 |
|
|
| createdAt | created_at | 1:1 (BaseTimeEntity) |
|
|
| updatedAt | updated_at | 1:1 (BaseTimeEntity) |
|
|
|
|
---
|
|
|
|
## 3. 데이터 관계
|
|
|
|
### 3.1 테이블 간 관계
|
|
|
|
```
|
|
distribution_status (1) ----< (N) channel_status
|
|
- 하나의 배포 상태는 여러 채널 상태를 가짐
|
|
- CASCADE DELETE: 배포 상태 삭제 시 채널 상태도 함께 삭제
|
|
```
|
|
|
|
### 3.2 인덱스 전략
|
|
|
|
**distribution_status 테이블**:
|
|
- PRIMARY KEY: id (클러스터 인덱스)
|
|
- UNIQUE INDEX: event_id (이벤트별 배포 상태 유일성 보장)
|
|
|
|
**channel_status 테이블**:
|
|
- PRIMARY KEY: id (클러스터 인덱스)
|
|
- UNIQUE INDEX: (distribution_status_id, channel) (배포당 채널별 유일성)
|
|
- INDEX: event_id (이벤트별 채널 상태 조회 최적화)
|
|
- INDEX: (event_id, channel) (복합 조회 최적화)
|
|
- INDEX: status (상태별 필터링 최적화)
|
|
|
|
---
|
|
|
|
## 4. 데이터 독립성 설계
|
|
|
|
### 4.1 서비스 간 데이터 분리
|
|
|
|
**Distribution Service 데이터 소유권**:
|
|
- 배포 상태 및 채널별 성과 데이터 완전 소유
|
|
- 타 서비스의 데이터를 직접 조회하지 않음
|
|
|
|
**타 서비스 데이터 참조**:
|
|
- **Event ID**: Event Service에서 생성한 ID를 참조 (FK 없음)
|
|
- **User ID**: 직접 저장하지 않음 (인증 정보로만 사용)
|
|
- **참조 방식**: Redis 캐시 또는 Kafka 이벤트로만 참조
|
|
|
|
### 4.2 데이터 동기화 전략
|
|
|
|
**Kafka 이벤트 발행**:
|
|
```java
|
|
// 배포 완료 시 이벤트 발행
|
|
Topic: distribution-completed
|
|
Event: {
|
|
"eventId": "uuid",
|
|
"distributedChannels": [
|
|
{
|
|
"channel": "INSTAGRAM",
|
|
"status": "SUCCESS",
|
|
"expectedViews": 5000
|
|
}
|
|
],
|
|
"completedAt": "2025-10-29T11:00:00"
|
|
}
|
|
```
|
|
|
|
**Analytics Service 연동**:
|
|
- Distribution Service → Kafka → Analytics Service
|
|
- 채널별 성과 데이터 비동기 전달
|
|
- 장애 격리 보장 (Circuit Breaker)
|
|
|
|
---
|
|
|
|
## 5. 쿼리 성능 최적화
|
|
|
|
### 5.1 조회 쿼리 최적화
|
|
|
|
**이벤트별 배포 상태 조회**:
|
|
```sql
|
|
-- 인덱스 활용: event_id
|
|
SELECT ds.*, cs.*
|
|
FROM distribution_status ds
|
|
LEFT JOIN channel_status cs ON ds.id = cs.distribution_status_id
|
|
WHERE ds.event_id = ?;
|
|
```
|
|
|
|
**채널별 배포 현황 조회**:
|
|
```sql
|
|
-- 인덱스 활용: (event_id, channel)
|
|
SELECT *
|
|
FROM channel_status
|
|
WHERE event_id = ? AND channel = ?;
|
|
```
|
|
|
|
**진행 중인 배포 목록 조회**:
|
|
```sql
|
|
-- 인덱스 활용: overall_status
|
|
SELECT *
|
|
FROM distribution_status
|
|
WHERE overall_status = 'IN_PROGRESS'
|
|
ORDER BY started_at DESC;
|
|
```
|
|
|
|
### 5.2 캐시 전략
|
|
|
|
**조회 우선순위**:
|
|
1. Redis 캐시 조회 시도
|
|
2. 캐시 미스 시 PostgreSQL 조회
|
|
3. 조회 결과를 Redis에 캐싱
|
|
|
|
**캐시 무효화**:
|
|
- 배포 상태 업데이트 시 캐시 갱신
|
|
- 배포 완료 시 캐시 TTL 연장 (1시간 → 24시간)
|
|
- 채널 상태 변경 시 해당 채널 캐시 갱신
|
|
|
|
---
|
|
|
|
## 6. 데이터 보안 및 제약
|
|
|
|
### 6.1 데이터 무결성
|
|
|
|
**NOT NULL 제약**:
|
|
- 필수 정보: event_id, channel, status, overall_status
|
|
- 시간 정보: started_at, update_timestamp
|
|
|
|
**CHECK 제약**:
|
|
- overall_status: 4가지 상태만 허용
|
|
- channel: 6개 채널 타입만 허용
|
|
- status: 4가지 배포 상태만 허용
|
|
- progress: 0-100 범위 제한
|
|
|
|
**UNIQUE 제약**:
|
|
- event_id: 이벤트당 하나의 배포 상태
|
|
- (distribution_status_id, channel): 배포당 채널별 하나의 상태
|
|
|
|
### 6.2 CASCADE 정책
|
|
|
|
**ON DELETE CASCADE**:
|
|
- distribution_status 삭제 시 channel_status 자동 삭제
|
|
- 데이터 일관성 보장
|
|
|
|
---
|
|
|
|
## 7. 마이그레이션 전략
|
|
|
|
### 7.1 초기 데이터 마이그레이션
|
|
- 초기 배포 시 기본 데이터 없음 (운영 데이터만 존재)
|
|
- 채널 타입 Enum 검증 데이터 확인
|
|
|
|
### 7.2 스키마 변경 전략
|
|
- Flyway 또는 Liquibase를 통한 버전 관리
|
|
- 무중단 배포를 위한 Blue-Green 전략
|
|
- 인덱스 추가 시 CONCURRENTLY 옵션 사용
|
|
|
|
---
|
|
|
|
## 8. 모니터링 및 유지보수
|
|
|
|
### 8.1 성능 모니터링 지표
|
|
- 배포 상태 조회 응답 시간 (<100ms)
|
|
- 채널별 배포 성공률 (>95%)
|
|
- 재시도 횟수 평균 (<2회)
|
|
- 캐시 히트율 (>80%)
|
|
|
|
### 8.2 데이터 정리 정책
|
|
- 완료된 배포 상태: 30일 후 아카이빙
|
|
- 실패한 배포 로그: 90일 보관
|
|
- Redis 캐시: TTL 자동 만료
|
|
|
|
---
|
|
|
|
## 9. 참고 자료
|
|
|
|
### 9.1 관련 문서
|
|
- 클래스 설계서: `design/backend/class/distribution-service.puml`
|
|
- API 설계서: `design/backend/api/distribution-service-api.md`
|
|
- 시퀀스 다이어그램: `design/backend/sequence/inner/distribution-service-*.puml`
|
|
|
|
### 9.2 외부 참조
|
|
- PostgreSQL 공식 문서: https://www.postgresql.org/docs/
|
|
- Redis 캐시 설계 가이드: https://redis.io/docs/manual/patterns/
|
|
|
|
---
|
|
|
|
**문서 버전**: v1.0
|
|
**작성일**: 2025-10-29
|
|
**작성자**: Backend Developer (최수연 "아키텍처")
|