# Redis 캐시 설치 계획서 - 개발환경 ## 1. 개요 ### 1.1 설치 목적 - 통신요금 관리 서비스의 **개발환경** Redis 캐시 구축 - 모든 마이크로서비스 공유 캐시 서버 운영 - 성능 최적화 및 외부 시스템 호출 최소화 - KOS 시스템 연동 데이터 캐싱 ### 1.2 참조 문서 - 물리아키텍처설계서: design/backend/physical/physical-architecture-dev.md - 데이터설계서: design/backend/database/data-design-summary.md - 백킹서비스설치방법: claude/backing-service-method.md ### 1.3 설계 원칙 - **개발 편의성**: 단순 구성, 빠른 배포 - **비용 효율성**: 메모리 전용 설정 - **성능 우선**: 모든 서비스 공유 캐시 - **단순성**: 복잡한 클러스터링 없음 ## 2. 시스템 요구사항 ### 2.1 환경 정보 - **환경**: Azure Kubernetes Service (AKS) 개발환경 - **네임스페이스**: phonebill-dev - **클러스터**: phonebill-dev-aks - **리소스 그룹**: phonebill-dev-rg - **Azure 리전**: Korea Central ### 2.2 기술 스택 | 구성요소 | 버전/사양 | 용도 | |----------|-----------|------| | Redis | 7.2 | 메인 캐시 엔진 | | Container Image | bitnami/redis:7.2 | 안정화된 Redis 이미지 | | 배포 방식 | StatefulSet | 데이터 일관성 보장 | | 스토리지 | 없음 (Memory Only) | 개발용 임시 데이터 | | 네트워크 | ClusterIP + NodePort | 내부/외부 접근 지원 | ### 2.3 리소스 할당 | 리소스 유형 | 최소 요구사항 | 최대 제한 | 비고 | |-------------|---------------|-----------|------| | CPU | 100m | 500m | 개발환경 최적화 | | Memory | 256Mi | 1Gi | 캐시 크기 제한 | | 최대 메모리 | 512MB | - | 메모리 정책 적용 | | 스토리지 | 없음 | - | 메모리 전용 | ## 3. 아키텍처 설계 ### 3.1 Redis 서비스 구성 ``` ┌─────────────────────────────────────────────────────────────┐ │ AKS Cluster (phonebill-dev) │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Auth Service │ │Bill-Inquiry Svc│ │ │ │ (Port: 8080) │ │ (Port: 8080) │ │ │ └─────────┬───────┘ └─────────┬───────┘ │ │ │ │ │ │ │ ┌─────────────────┐ │ │ │ │Product-Change │ │ │ │ │Service │ │ │ │ │ (Port: 8080) │ │ │ │ └─────────┬───────┘ │ │ │ │ │ │ └──────────┬───────────┘ │ │ │ │ │ ┌─────────────────┐ │ │ │ Redis Cache │ │ │ │ │ │ │ │ • Memory Only │ │ │ │ • Port: 6379 │ │ │ │ • Password Auth │ │ │ │ • LRU Policy │ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ### 3.2 캐시 키 전략 #### 3.2.1 키 네이밍 규칙 ```yaml 키_패턴: 고객정보: "customer:{lineNumber}" 상품정보: "product:{productCode}" 세션정보: "session:{userId}:{sessionId}" 권한정보: "permissions:{userId}" 가용상품: "available_products:{customerType}" 회선상태: "line_status:{lineNumber}" KOS응답: "kos_response:{requestId}" ``` #### 3.2.2 TTL 정책 | 캐시 유형 | TTL | 용도 | 갱신 전략 | |-----------|-----|------|-----------| | 고객정보 | 4시간 | 고객 기본정보 | 정보 변경시 즉시 무효화 | | 상품정보 | 2시간 | 상품 목록/상세 | 상품 업데이트시 무효화 | | 세션정보 | 24시간 | 사용자 세션 | 로그아웃시 삭제 | | 권한정보 | 8시간 | 사용자 권한 | 권한 변경시 무효화 | | 가용상품목록 | 24시간 | 변경 가능 상품 | 일 1회 갱신 | | 회선상태 | 30분 | 실시간 회선정보 | 상태 변경시 갱신 | ### 3.3 메모리 관리 전략 ```yaml 메모리_설정: 최대_메모리: "512MB" 정책: "allkeys-lru" # 가장 오래된 키 제거 기본_TTL: "30분" # 명시되지 않은 키의 기본 만료시간 메모리_분배: 세션정보: 40% (204MB) 고객정보: 30% (154MB) 상품정보: 20% (102MB) 기타: 10% (52MB) ``` ## 4. 설치 구성 ### 4.1 Namespace 생성 ```bash # Namespace 생성 kubectl create namespace phonebill-dev # Namespace 이동 kubectl config set-context --current --namespace=phonebill-dev ``` ### 4.2 Secret 생성 ```bash # Redis 인증 정보 생성 kubectl create secret generic redis-secret \ --from-literal=redis-password="Hi5Jessica!" \ --namespace=phonebill-dev ``` ### 4.3 ConfigMap 생성 ```yaml # redis-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: redis-config namespace: phonebill-dev data: redis.conf: | # Redis 7.2 개발환경 설정 # 메모리 설정 maxmemory 512mb maxmemory-policy allkeys-lru # 네트워크 설정 bind 0.0.0.0 port 6379 tcp-keepalive 300 timeout 30 # 보안 설정 (Secret에서 주입) # requirepass 는 StatefulSet에서 env로 설정 # 로그 설정 loglevel notice logfile "" # 개발환경 설정 (데이터 지속성 없음) save "" appendonly no # 클라이언트 설정 maxclients 100 # 기타 최적화 설정 tcp-backlog 511 databases 16 # 메모리 사용 최적화 hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 ``` ### 4.4 StatefulSet 매니페스트 ```yaml # redis-statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: redis namespace: phonebill-dev labels: app: redis tier: cache spec: serviceName: redis replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis tier: cache spec: containers: - name: redis image: bitnami/redis:7.2 imagePullPolicy: IfNotPresent # 환경 변수 env: - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: redis-password - name: REDIS_DISABLE_COMMANDS value: "FLUSHALL" # 개발 중 실수 방지 # 포트 설정 ports: - name: redis containerPort: 6379 protocol: TCP # 리소스 제한 resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 1Gi # Health Check livenessProbe: tcpSocket: port: redis initialDelaySeconds: 30 timeoutSeconds: 5 periodSeconds: 10 failureThreshold: 3 readinessProbe: exec: command: - /bin/bash - -c - redis-cli -a "$REDIS_PASSWORD" ping | grep -q PONG initialDelaySeconds: 5 timeoutSeconds: 5 periodSeconds: 5 successThreshold: 1 failureThreshold: 3 # 볼륨 마운트 volumeMounts: - name: redis-config mountPath: /opt/bitnami/redis/etc/redis.conf subPath: redis.conf readOnly: true # 볼륨 정의 volumes: - name: redis-config configMap: name: redis-config # 보안 컨텍스트 securityContext: fsGroup: 1001 runAsUser: 1001 runAsNonRoot: true # Pod 안정성 설정 restartPolicy: Always terminationGracePeriodSeconds: 30 ``` ### 4.5 Service 매니페스트 ```yaml # redis-service.yaml apiVersion: v1 kind: Service metadata: name: redis namespace: phonebill-dev labels: app: redis tier: cache spec: type: ClusterIP selector: app: redis ports: - name: redis port: 6379 targetPort: redis protocol: TCP --- # 개발용 외부 접근 Service apiVersion: v1 kind: Service metadata: name: redis-external namespace: phonebill-dev labels: app: redis tier: cache spec: type: NodePort selector: app: redis ports: - name: redis port: 6379 targetPort: redis nodePort: 30679 protocol: TCP ``` ## 5. 배포 절차 ### 5.1 사전 준비사항 ```bash # 1. AKS 클러스터 연결 확인 kubectl config current-context # 2. 필요한 권한 확인 kubectl auth can-i create statefulsets --namespace phonebill-dev # 3. 네임스페이스 확인 kubectl get namespaces | grep phonebill-dev ``` ### 5.2 배포 순서 ```bash # 1. Namespace 생성 kubectl create namespace phonebill-dev # 2. Secret 생성 kubectl create secret generic redis-secret \ --from-literal=redis-password="Hi5Jessica!" \ --namespace=phonebill-dev # 3. ConfigMap 적용 kubectl apply -f redis-config.yaml # 4. StatefulSet 배포 kubectl apply -f redis-statefulset.yaml # 5. Service 생성 kubectl apply -f redis-service.yaml # 6. 배포 상태 확인 kubectl get pods -l app=redis -n phonebill-dev -w ``` ### 5.3 배포 검증 ```bash # 1. Pod 상태 확인 kubectl get pods -l app=redis -n phonebill-dev kubectl describe pod redis-0 -n phonebill-dev # 2. Service 확인 kubectl get services -l app=redis -n phonebill-dev kubectl describe service redis -n phonebill-dev # 3. Redis 연결 테스트 kubectl exec -it redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! ping # 4. 설정 확인 kubectl exec -it redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info memory ``` ## 6. 애플리케이션 연동 설정 ### 6.1 Spring Boot 애플리케이션 설정 ```yaml # application-dev.yml spring: redis: host: redis.phonebill-dev.svc.cluster.local port: 6379 password: ${REDIS_PASSWORD:Hi5Jessica!} timeout: 2000ms jedis: pool: max-active: 20 max-wait: 1000ms max-idle: 10 min-idle: 2 # 캐시 설정 cache: redis: time-to-live: 1800 # 30분 기본 TTL key-prefix: "phonebill:dev:" enable-statistics: true ``` ### 6.2 환경별 캐시 키 설정 ```yaml # 개발환경 캐시 키 설정 cache: keys: customer: "dev:customer:{lineNumber}" product: "dev:product:{productCode}" session: "dev:session:{userId}:{sessionId}" permissions: "dev:permissions:{userId}" available-products: "dev:available_products:{customerType}" line-status: "dev:line_status:{lineNumber}" kos-response: "dev:kos_response:{requestId}" ``` ### 6.3 서비스별 캐시 설정 ```java // Auth Service 캐시 설정 @Configuration public class AuthCacheConfig { @Bean public RedisCacheManager authCacheManager() { RedisCacheConfiguration config = RedisCacheConfiguration .defaultCacheConfig() .entryTtl(Duration.ofHours(8)) // 권한정보 8시간 .prefixKeysWith("dev:auth:"); return RedisCacheManager.builder() .redisCacheConfiguration(config) .build(); } } // Bill-Inquiry Service 캐시 설정 @Configuration public class BillCacheConfig { @Bean public RedisCacheManager billCacheManager() { RedisCacheConfiguration config = RedisCacheConfiguration .defaultCacheConfig() .entryTtl(Duration.ofHours(4)) // 고객정보 4시간 .prefixKeysWith("dev:bill:"); return RedisCacheManager.builder() .redisCacheConfiguration(config) .build(); } } // Product-Change Service 캐시 설정 @Configuration public class ProductCacheConfig { @Bean public RedisCacheManager productCacheManager() { RedisCacheConfiguration config = RedisCacheConfiguration .defaultCacheConfig() .entryTtl(Duration.ofHours(2)) // 상품정보 2시간 .prefixKeysWith("dev:product:"); return RedisCacheManager.builder() .redisCacheConfiguration(config) .build(); } } ``` ## 7. 모니터링 설정 ### 7.1 Redis 메트릭 수집 ```yaml # redis-metrics.yaml apiVersion: v1 kind: Service metadata: name: redis-metrics namespace: phonebill-dev labels: app: redis metrics: "true" spec: selector: app: redis ports: - name: metrics port: 9121 targetPort: 9121 --- apiVersion: apps/v1 kind: Deployment metadata: name: redis-exporter namespace: phonebill-dev spec: selector: matchLabels: app: redis-exporter template: metadata: labels: app: redis-exporter spec: containers: - name: redis-exporter image: oliver006/redis_exporter:latest env: - name: REDIS_ADDR value: "redis://redis:6379" - name: REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: redis-password ports: - containerPort: 9121 name: metrics resources: requests: cpu: 50m memory: 64Mi limits: cpu: 200m memory: 128Mi ``` ### 7.2 주요 모니터링 지표 | 지표 | 임계값 | 액션 | |------|--------|------| | 메모리 사용률 | > 80% | 캐시 정리, 메모리 증설 검토 | | 연결 수 | > 80 | 연결 풀 최적화 | | Hit Rate | < 80% | 캐시 전략 재검토 | | Evicted Keys | > 1000/min | TTL 정책 조정 | | 응답 시간 | > 10ms | 성능 최적화 | ### 7.3 로그 모니터링 ```bash # Redis 로그 실시간 모니터링 kubectl logs -f redis-0 -n phonebill-dev # 메모리 사용량 모니터링 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info memory # 키 통계 모니터링 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info keyspace # 클라이언트 연결 상태 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! client list ``` ## 8. 백업 및 복구 ### 8.1 백업 전략 ```yaml 백업_정책: 방식: "메모리 전용으로 백업 없음" 복구_방법: "Pod 재시작시 캐시 재구성" 데이터_손실: "허용 (개발환경)" 비상_계획: - Pod 장애시 자동 재시작 - 애플리케이션에서 캐시 미스시 DB 조회 - 캐시 warm-up 스크립트 실행 ``` ### 8.2 캐시 Warm-up 스크립트 ```bash #!/bin/bash # cache-warmup.sh - Redis 재시작 후 주요 데이터 캐싱 REDIS_HOST="redis.phonebill-dev.svc.cluster.local" REDIS_PORT="6379" REDIS_PASSWORD="Hi5Jessica!" # 기본 상품 정보 캐싱 echo "상품 정보 캐싱 시작..." curl -X POST "http://auth-service:8080/api/cache/warmup/products" # 공통 코드 캐싱 echo "공통 코드 캐싱 시작..." curl -X POST "http://auth-service:8080/api/cache/warmup/codes" # 시스템 설정 캐싱 echo "시스템 설정 캐싱 시작..." curl -X POST "http://bill-inquiry-service:8080/api/cache/warmup/config" echo "캐시 Warm-up 완료" ``` ## 9. 보안 설정 ### 9.1 네트워크 보안 ```yaml # redis-network-policy.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: redis-network-policy namespace: phonebill-dev spec: podSelector: matchLabels: app: redis policyTypes: - Ingress ingress: # 애플리케이션 서비스에서만 접근 허용 - from: - podSelector: matchLabels: tier: application ports: - protocol: TCP port: 6379 # 모니터링을 위한 접근 허용 - from: - podSelector: matchLabels: app: redis-exporter ports: - protocol: TCP port: 6379 ``` ### 9.2 보안 체크리스트 ```yaml 보안_체크리스트: ✓ 인증: "Redis 패스워드 인증 활성화" ✓ 네트워크: "ClusterIP로 내부 접근만 허용" ✓ 권한: "비루트 사용자로 실행" ✓ 명령어: "위험한 명령어 비활성화 (FLUSHALL)" ✓ 로그: "접근 로그 기록" ✗ 암호화: "개발환경에서 TLS 미적용" ✗ 방화벽: "기본 보안 그룹 사용" ``` ## 10. 운영 가이드 ### 10.1 일상 운영 작업 ```bash # Redis 상태 확인 kubectl get pods -l app=redis -n phonebill-dev kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info server # 메모리 사용량 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info memory # 키 현황 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info keyspace # 슬로우 로그 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! slowlog get 10 ``` ### 10.2 캐시 관리 작업 ```bash # 특정 패턴 키 삭제 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! --scan --pattern "dev:customer:*" | xargs -I {} redis-cli -a Hi5Jessica! del {} # 캐시 통계 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! info stats # 클라이언트 연결 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! client list # TTL 확인 kubectl exec redis-0 -n phonebill-dev -- redis-cli -a Hi5Jessica! ttl "dev:customer:010-1234-5678" ``` ### 10.3 트러블슈팅 가이드 | 문제 | 원인 | 해결방안 | |------|------|----------| | Pod 시작 실패 | 리소스 부족 | 노드 리소스 확인, 메모리 제한 조정 | | 연결 실패 | 네트워크/인증 문제 | 패스워드, 포트, 네트워크 정책 확인 | | 메모리 부족 | 캐시 데이터 과다 | TTL 정책 조정, 메모리 증설 | | 성능 저하 | 키 집중, 메모리 스왑 | 키 분산, 메모리 최적화 | | 캐시 미스 증가 | TTL 정책, 데이터 변경 | TTL 조정, 무효화 전략 검토 | ## 11. 비용 최적화 ### 11.1 개발환경 비용 구조 | 리소스 | 할당량 | 월간 예상 비용 | 절약 방안 | |--------|---------|----------------|-----------| | CPU | 100m-500m | $3 | requests 최소화 | | Memory | 256Mi-1Gi | $5 | 메모리 전용으로 스토리지 비용 없음 | | 네트워킹 | ClusterIP | $0 | 내부 통신만 사용 | | **총합** | | **$8** | **스토리지 제거로 비용 최소화** | ### 11.2 비용 절약 전략 ```yaml 절약_방안: - 스토리지_제거: "메모리 전용으로 스토리지 비용 제거" - 리소스_최적화: "requests를 최소한으로 설정" - 자동_스케일링_비활성화: "개발환경에서 고정 리소스" - 야간_스케일다운: "비업무시간 리소스 축소" ``` ## 12. 성능 튜닝 가이드 ### 12.1 성능 목표 | 지표 | 목표값 | 측정 방법 | |------|---------|-----------| | 응답 시간 | < 5ms | Redis PING | | 처리량 | > 1000 ops/sec | Redis INFO stats | | 메모리 효율성 | > 90% hit rate | Redis INFO keyspace | | 연결 처리 | < 100 concurrent | Redis CLIENT LIST | ### 12.2 튜닝 매개변수 ```yaml # redis.conf 최적화 성능_튜닝: # 네트워크 최적화 tcp-keepalive: 300 tcp-backlog: 511 timeout: 30 # 메모리 최적화 maxmemory-policy: "allkeys-lru" hash-max-ziplist-entries: 512 list-max-ziplist-size: -2 # 클라이언트 최적화 maxclients: 100 databases: 16 ``` ## 13. 마이그레이션 계획 ### 13.1 운영환경 이관 준비 ```yaml 운영환경_차이점: - 고가용성: "Master-Slave 구성" - 데이터_지속성: "RDB + AOF 활성화" - 보안_강화: "TLS 암호화, 네트워크 정책" - 리소스_증설: "CPU 1-2 core, Memory 4-8GB" - 모니터링_강화: "Prometheus, Grafana 연동" - 백업_정책: "자동 백업, 복구 절차" ``` ### 13.2 설정 호환성 ```yaml 호환성_체크: ✓ Redis_버전: "7.2 동일" ✓ 데이터_구조: "키 패턴 호환" ✓ 애플리케이션_설정: "연결 정보만 변경" ✓ 모니터링_지표: "동일한 메트릭 수집" ⚠ TTL_정책: "운영환경에서 조정 필요" ⚠ 메모리_정책: "운영환경 특성에 맞게 조정" ``` ## 14. 완료 체크리스트 ### 14.1 설치 검증 항목 ```yaml 필수_검증_항목: □ Redis Pod 정상 실행 □ Service 연결 가능 □ 패스워드 인증 동작 □ 메모리 제한 적용 □ TTL 정책 동작 □ 애플리케이션 연동 테스트 □ 모니터링 메트릭 수집 □ 네트워크 정책 적용 □ 캐시 성능 테스트 □ 장애 복구 테스트 ``` ### 14.2 운영 준비 항목 ```yaml 운영_준비_항목: □ 운영 매뉴얼 작성 □ 모니터링 대시보드 구성 □ 알림 규칙 설정 □ 백업 및 복구 절차 문서화 □ 성능 튜닝 가이드 작성 □ 트러블슈팅 가이드 작성 □ 개발팀 교육 완료 □ 운영팀 인수인계 완료 ``` --- **계획서 작성일**: `2025-09-08` **작성자**: 데옵스 (최운영), 백엔더 (이개발) **검토자**: 아키텍트 (김기획), QA매니저 (정테스트) **승인자**: 프로젝트 매니저 **다음 단계**: Redis 캐시 설치 실행 → develop/database/exec/cache-exec-dev.md 작성