Files
SR-SYSTEM/docs/02-architecture.md
2026-06-02 13:50:39 +09:00

9.2 KiB

시스템 아키텍처 정의서 (System Architecture)

1. 기술 스택

계층 기술 버전
Backend Spring Boot 3.x
Java 17
Spring Data JPA -
Spring Security -
Spring Batch -
Frontend Next.js 14+ (App Router)
TypeScript -
Tailwind CSS -
Pinia (State Management) -
Database PostgreSQL 15
Infra Nginx Proxy Manager -
CI/CD GitHub Actions Release 트리거
Notification Slack Webhook / Email -

2. 전역 시스템 레이어 구조

┌─────────────────────────────────────────────────────────────┐
│                     Frontend (Next.js 14+)                    │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐  │
│  │ Pinia    │ │ Axios    │ │ Tailwind │ │  Dynamic LNB  │  │
│  │ Storage  │ │ Intercep.│ │ CSS      │ │  (RBAC)       │  │
│  └──────────┘ └──────────┘ └──────────┘ └───────────────┘  │
└──────────────────────┬──────────────────────────────────────┘
                       │ HTTPS / REST API
                       ▼
┌─────────────────────────────────────────────────────────────┐
│              Cloudflare Tunnel (SSL / Zero-Trust Proxy)       │
└─────────────────────────────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│              Backend (Spring Boot 3.x / Java 17)             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Security Layer                                      │   │
│  │  ┌─────────────────┐  ┌──────────────────────────┐  │   │
│  │  │ JWT Token       │  │ Security Filter Chain    │  │   │
│  │  │ Provider        │  │ (RBAC Authorization)     │  │   │
│  │  └─────────────────┘  └──────────────────────────┘  │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  API Layer (REST Controllers)                        │   │
│  │  EmployeeController / TicketController / ...         │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Service Layer (Business Logic + Transaction)        │   │
│  │  ├─ @Transactional 선언                              │   │
│  │  └─ ApplicationEventPublisher (EDA 발행)              │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Persistence Layer (Spring Data JPA)                 │   │
│  │  ├─ Entity / Repository / Specification              │   │
│  │  ├─ @SQLDelete + @Where (Soft Delete 전역 필터)      │   │
│  │  └─ @SequenceGenerator(allocationSize=50)            │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Infrastructure Layer                                │   │
│  │  ├─ @TransactionalEventListener(AFTER_COMMIT)        │   │
│  │  ├─ @Async Notification Listener                     │   │
│  │  └─ Spring Batch SLA Scheduler (Chunk Size=100)      │   │
│  └──────────────────────────────────────────────────────┘   │
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│              PostgreSQL 15 Database                            │
│  ├─ Sequence (INCREMENT BY 50)                               │
│  ├─ Common Code Table (동적 드롭다운)                        │
│  └─ Batch Metadata Schema                                    │
└─────────────────────────────────────────────────────────────┘

3. ApiResponse 공통 규격

모든 API 응답은 아래 포맷을 강제합니다.

성공:

{
  "success": true,
  "message": "요청이 성공적으로 처리되었습니다.",
  "data": { ... }
}

실패 (비즈니스 예외):

{
  "success": false,
  "message": "이미 결재가 완료된 보고서는 수정할 수 없습니다.",
  "errorCode": "RPT_ERR_001",
  "data": null
}

4. 글로벌 예외 처리 (GlobalExceptionHandler)

  • 모든 도메인 예외는 BusinessException (RuntimeException 상속) 통일
  • @RestControllerAdvice가 감지 → ErrorCode Enum 매핑 → ApiResponse.error() 변환

ErrorCode 매트릭스

Enum HTTP Status ErrorCode 메시지
RESIGNED_EMPLOYEE 400 EMP_ERR_001 퇴사 처리된 직원 정보는 수정할 수 없습니다
LOCKED_REPORT 400 RPT_ERR_001 결재 완료 보고서는 수정/삭제할 수 없습니다
FUTURE_REPORT_DATE 400 RPT_ERR_002 미래 날짜의 업무 보고는 작성할 수 없습니다
CLOSED_TICKET_MOD 400 TCK_ERR_001 종료된 티켓은 댓글/수정이 불가능합니다
ASSIGNEE_REQUIRED 400 TCK_ERR_002 담당자 미배정 티켓은 IN_PROGRESS 전환 불가
EQUIP_NOT_AVAILABLE 400 EQP_ERR_001 지급 가능한 재고 상태가 아닙니다
INVALID_ASSIGNEE 400 EQP_ERR_002 재직 중인 직원에게만 장비 지급 가능
SYSTEM_CONCURRENCY 409 SYS_ERR_001 동시성 충돌 - 다시 시도해 주세요

5. 이벤트 기반 비동기 알림 (EDA)

sequenceDiagram
    Controller->>Service: 요청 처리
    Service->>DB: 트랜잭션 커밋
    Service->>EventPublisher: 이벤트 발행
    EventPublisher->>Listener: @TransactionalEventListener(AFTER_COMMIT)
    Listener->>Slack/Email: @Async 비동기 발송
    Note over Listener: 메인 트랜잭션과 완전 격리

6. SLA 만료 배치 아키텍처 (Spring Batch)

  • 트리거: Spring Scheduler (매시간)
  • Chunk Size: 100건 단위 청크 분할
  • 필터 조건: SLA_WARN_FLAG = 'N' AND status NOT IN (RESOLVED, CLOSED) AND due_date < NOW()
  • 처리: 대상 티켓 탐색 → 알림 이벤트 발행 → SLA_WARN_FLAG = 'Y' 갱신
  • PostgreSQL 메타데이터: 배치 전용 메타 테이블 스키마 별도 구축

7. Soft Delete 전역 아키텍처

// BaseEntity 패턴
@SQLDelete(sql = "UPDATE tb_xxx SET is_deleted = 'Y' WHERE id = ?")
@Where(clause = "is_deleted = 'N'")
  • 모든 엔티티가 BaseEntity 상속 (created_at, updated_at, is_deleted)
  • 조회 시 @Where 조건절 자동 적용 → 조건절 누수 방지
  • 물리 삭제 DELETE → UPDATE is_deleted='Y' 자변환