mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2026-06-13 14:59:13 +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>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
@startuml
|
||||
!theme mono
|
||||
|
||||
title 공통 컴포넌트 클래스 다이어그램
|
||||
|
||||
package "com.kt.event.common" {
|
||||
|
||||
package "entity" {
|
||||
abstract class BaseTimeEntity {
|
||||
- createdAt: LocalDateTime
|
||||
- updatedAt: LocalDateTime
|
||||
}
|
||||
}
|
||||
|
||||
package "dto" {
|
||||
class "ApiResponse<T>" {
|
||||
- success: boolean
|
||||
- data: T
|
||||
- errorCode: String
|
||||
- message: String
|
||||
- timestamp: LocalDateTime
|
||||
+ success(data: T): ApiResponse<T>
|
||||
+ success(): ApiResponse<T>
|
||||
+ error(errorCode: String, message: String): ApiResponse<T>
|
||||
}
|
||||
|
||||
class ErrorResponse {
|
||||
- success: boolean
|
||||
- errorCode: String
|
||||
- message: String
|
||||
- timestamp: LocalDateTime
|
||||
- details: Map<String, Object>
|
||||
+ of(errorCode: ErrorCode): ErrorResponse
|
||||
+ of(errorCode: ErrorCode, details: Map<String, Object>): ErrorResponse
|
||||
}
|
||||
|
||||
class "PageResponse<T>" {
|
||||
- content: List<T>
|
||||
- totalElements: long
|
||||
- totalPages: int
|
||||
- number: int
|
||||
- size: int
|
||||
- first: boolean
|
||||
- last: boolean
|
||||
+ of(content: List<T>, pageable: Pageable, total: long): PageResponse<T>
|
||||
}
|
||||
}
|
||||
|
||||
package "exception" {
|
||||
interface ErrorCode {
|
||||
+ getCode(): String
|
||||
+ getMessage(): String
|
||||
}
|
||||
|
||||
enum CommonErrorCode implements ErrorCode {
|
||||
COMMON_001
|
||||
COMMON_002
|
||||
COMMON_003
|
||||
COMMON_004
|
||||
COMMON_005
|
||||
NOT_FOUND
|
||||
INVALID_INPUT_VALUE
|
||||
AUTH_001 ~ AUTH_005
|
||||
USER_001 ~ USER_005
|
||||
EVENT_001 ~ EVENT_005
|
||||
JOB_001 ~ JOB_004
|
||||
AI_001 ~ AI_004
|
||||
CONTENT_001 ~ CONTENT_004
|
||||
DIST_001 ~ DIST_004
|
||||
PART_001 ~ PART_008
|
||||
ANALYTICS_001 ~ ANALYTICS_003
|
||||
EXTERNAL_001 ~ EXTERNAL_003
|
||||
DB_001 ~ DB_004
|
||||
REDIS_001 ~ REDIS_003
|
||||
KAFKA_001 ~ KAFKA_003
|
||||
- code: String
|
||||
- message: String
|
||||
+ getCode(): String
|
||||
+ getMessage(): String
|
||||
}
|
||||
|
||||
class BusinessException extends RuntimeException {
|
||||
- errorCode: ErrorCode
|
||||
- details: String
|
||||
+ BusinessException(errorCode: ErrorCode)
|
||||
+ BusinessException(errorCode: ErrorCode, message: String)
|
||||
+ BusinessException(errorCode: ErrorCode, message: String, details: String)
|
||||
+ BusinessException(errorCode: ErrorCode, cause: Throwable)
|
||||
+ BusinessException(errorCode: ErrorCode, message: String, details: String, cause: Throwable)
|
||||
+ getErrorCode(): ErrorCode
|
||||
+ getDetails(): String
|
||||
}
|
||||
|
||||
class InfraException extends RuntimeException {
|
||||
- errorCode: ErrorCode
|
||||
- details: String
|
||||
+ InfraException(errorCode: ErrorCode)
|
||||
+ InfraException(errorCode: ErrorCode, message: String)
|
||||
+ InfraException(errorCode: ErrorCode, cause: Throwable)
|
||||
+ getErrorCode(): ErrorCode
|
||||
+ getDetails(): String
|
||||
}
|
||||
}
|
||||
|
||||
package "util" {
|
||||
class ValidationUtil {
|
||||
+ requireNonNull(object: Object, errorCode: ErrorCode): void
|
||||
+ requireNonNull(object: Object, errorCode: ErrorCode, message: String): void
|
||||
+ requireNotBlank(str: String, errorCode: ErrorCode): void
|
||||
+ requireNotBlank(str: String, errorCode: ErrorCode, message: String): void
|
||||
+ require(condition: boolean, errorCode: ErrorCode): void
|
||||
+ require(condition: boolean, errorCode: ErrorCode, message: String): void
|
||||
+ requireValidPhoneNumber(phoneNumber: String, errorCode: ErrorCode): void
|
||||
+ requireValidEmail(email: String, errorCode: ErrorCode): void
|
||||
+ requireValidBusinessNumber(businessNumber: String, errorCode: ErrorCode): void
|
||||
+ requirePositive(value: long, errorCode: ErrorCode): void
|
||||
+ requireNonNegative(value: long, errorCode: ErrorCode): void
|
||||
+ requireInRange(value: long, min: long, max: long, errorCode: ErrorCode): void
|
||||
}
|
||||
|
||||
class StringUtil {
|
||||
+ isBlank(str: String): boolean
|
||||
+ isNotBlank(str: String): boolean
|
||||
+ hasText(str: String): boolean
|
||||
+ isEmpty(str: String): boolean
|
||||
+ isNotEmpty(str: String): boolean
|
||||
+ isValidEmail(email: String): boolean
|
||||
+ isValidPhoneNumber(phoneNumber: String): boolean
|
||||
+ isValidBusinessNumber(businessNumber: String): boolean
|
||||
+ maskEmail(email: String): String
|
||||
+ maskPhoneNumber(phoneNumber: String): String
|
||||
+ generateRandomString(length: int): String
|
||||
+ removeSpecialCharacters(str: String): String
|
||||
}
|
||||
|
||||
class DateTimeUtil {
|
||||
+ now(): LocalDateTime
|
||||
+ nowZoned(): ZonedDateTime
|
||||
+ toEpochMilli(dateTime: LocalDateTime): long
|
||||
+ fromEpochMilli(epochMilli: long): LocalDateTime
|
||||
+ format(dateTime: LocalDateTime, pattern: String): String
|
||||
+ parse(dateTimeString: String, pattern: String): LocalDateTime
|
||||
+ isAfter(dateTime1: LocalDateTime, dateTime2: LocalDateTime): boolean
|
||||
+ isBefore(dateTime1: LocalDateTime, dateTime2: LocalDateTime): boolean
|
||||
+ isDateInRange(target: LocalDateTime, start: LocalDateTime, end: LocalDateTime): boolean
|
||||
+ getDaysBetween(start: LocalDateTime, end: LocalDateTime): long
|
||||
}
|
||||
|
||||
class EncryptionUtil {
|
||||
+ encrypt(plainText: String): String
|
||||
+ decrypt(encryptedText: String): String
|
||||
+ hash(plainText: String): String
|
||||
+ matches(plainText: String, hashedText: String): boolean
|
||||
+ generateSalt(): String
|
||||
+ encryptWithSalt(plainText: String, salt: String): String
|
||||
}
|
||||
}
|
||||
|
||||
package "security" {
|
||||
class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
- jwtTokenProvider: JwtTokenProvider
|
||||
- userDetailsService: UserDetailsService
|
||||
+ doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain): void
|
||||
- extractTokenFromRequest(request: HttpServletRequest): String
|
||||
- authenticateUser(token: String): void
|
||||
}
|
||||
|
||||
interface JwtTokenProvider {
|
||||
+ generateToken(userDetails: UserDetails): String
|
||||
+ validateToken(token: String): boolean
|
||||
+ getUsernameFromToken(token: String): String
|
||||
+ getExpirationDateFromToken(token: String): Date
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
' 관계 정의
|
||||
BusinessException --> ErrorCode : uses
|
||||
InfraException --> ErrorCode : uses
|
||||
ValidationUtil --> ErrorCode : uses
|
||||
ValidationUtil --> StringUtil : uses
|
||||
ErrorResponse --> ErrorCode : uses
|
||||
|
||||
note top of BaseTimeEntity : JPA Auditing을 위한 기본 엔티티\n모든 도메인 엔티티가 상속
|
||||
note top of "ApiResponse<T>" : 모든 API 응답을 감싸는\n표준 응답 포맷
|
||||
note top of CommonErrorCode : 시스템 전체에서 사용하는\n표준 에러 코드
|
||||
note top of ValidationUtil : 비즈니스 로직에서 사용하는\n공통 유효성 검증 기능
|
||||
|
||||
@enduml
|
||||
Reference in New Issue
Block a user