diff --git a/.forge/role-aa-live-v4-001-attempt-1-run-c9c418513d91.md b/.forge/role-aa-live-v4-001-attempt-1-run-c9c418513d91.md new file mode 100644 index 0000000..cd9d370 --- /dev/null +++ b/.forge/role-aa-live-v4-001-attempt-1-run-c9c418513d91.md @@ -0,0 +1,3 @@ +# role-aa-live-v4-001-attempt-1-run-c9c418513d91 + +Forge 이슈 작업 브랜치 `forge/role-aa-live-v4-001-attempt-1-run-c9c418513d91`. diff --git a/.forge/role-developer-live-v4-001-attempt-1-run-844cb520d1b9.md b/.forge/role-developer-live-v4-001-attempt-1-run-844cb520d1b9.md new file mode 100644 index 0000000..ecb65ce --- /dev/null +++ b/.forge/role-developer-live-v4-001-attempt-1-run-844cb520d1b9.md @@ -0,0 +1,3 @@ +# role-developer-live-v4-001-attempt-1-run-844cb520d1b9 + +Forge 이슈 작업 브랜치 `forge/role-developer-live-v4-001-attempt-1-run-844cb520d1b9`. diff --git a/.forge/role-pm-live-v4-001-attempt-1-run-559d6d42668c.md b/.forge/role-pm-live-v4-001-attempt-1-run-559d6d42668c.md new file mode 100644 index 0000000..1ed56fe --- /dev/null +++ b/.forge/role-pm-live-v4-001-attempt-1-run-559d6d42668c.md @@ -0,0 +1,3 @@ +# role-pm-live-v4-001-attempt-1-run-559d6d42668c + +Forge 이슈 작업 브랜치 `forge/role-pm-live-v4-001-attempt-1-run-559d6d42668c`. diff --git a/.forge/role-ta-live-v4-001-attempt-1-run-e673c9d05e60.md b/.forge/role-ta-live-v4-001-attempt-1-run-e673c9d05e60.md new file mode 100644 index 0000000..c174a80 --- /dev/null +++ b/.forge/role-ta-live-v4-001-attempt-1-run-e673c9d05e60.md @@ -0,0 +1,3 @@ +# role-ta-live-v4-001-attempt-1-run-e673c9d05e60 + +Forge 이슈 작업 브랜치 `forge/role-ta-live-v4-001-attempt-1-run-e673c9d05e60`. diff --git a/docs/adr/ADR-001-spring-boundary-smoke.adoc b/docs/adr/ADR-001-spring-boundary-smoke.adoc new file mode 100644 index 0000000..43b90bf --- /dev/null +++ b/docs/adr/ADR-001-spring-boundary-smoke.adoc @@ -0,0 +1,152 @@ += ADR-001: TA 역할 Spring 경계 Smoke 테스트 설계 +:doctype: architecture-decision-record +:status: accepted +:date: 2025-07-14 +:deciders: TA + +== Context + +TA(Tech Architect) 역할은 Spring 기반 마이크로서비스 아키텍처에서 Controller-Service-Repository 경계의 명확한 분리와 오류 계약, 트랜잭션 경계를 정의해야 한다. + +현재 시스템은 다음 요구사항을 만족해야 한다: + +* **경계 명확성**: Controller는 외부 요청을 수신하고, Service는 비즈니스 로직을 수행하며, Repository는 데이터 접근을 담당한다. +* **오류 계약**: 각 계층 간 일관된 예외 처리와 오류 응답 구조를 보장한다. +* **트랜잭션 경계**: 데이터 일관성을 유지하면서 필요한 범위에서만 트랜잭션을 적용한다. + +== Decision + +=== 1. Controller-Service-Repository 경계 정의 + +[cols="1,2,3"] +|=== +| 계층 | 책임 |Forbidden Dependencies + +| `*Controller*` | HTTP 요청/응답 변환, 입력 검증, HTTP 상태 코드 관리 | Service 직접 호출 불가, Repository 직접 접근 금지 + +| `*Service*` | 비즈니스 로직 수행, 도메인 규칙 적용, 트랜잭션 관리 | Controller 직접 참조 불가, Web 관련 어노테이션 사용 금지 + +| `*Repository*` | 데이터 접근 추상화, JPA Entity 관리, 쿼리 실행 | 비즈니스 로직 포함 금지, HTTP 관련 코드 금지 +|=== + +==== 경계 규칙 + +* **Controller → Service**: DTO를 통해 통신, Service 인터페이스 또는 구체 클래스를 직접 호출 가능 +* **Service → Repository**: 도메인 Entity 또는 DTO를 전달, JPA Repository 인터페이스 호출 +* **하위 계층 → 상위 계층**: 의존성 없음 (Repository는 Service를 모름, Service는 Controller를 모름) + +=== 2. 오류 계약 정의 + +[cols="1,2,3"] +|=== +| 오류 유형 | 발생 계층 | HTTP 응답 + +| `*ValidationException*` | Controller | 400 Bad Request + `{ "code": "VALIDATION_ERROR", "message": "..." }` + +| `*ResourceNotFoundException*` | Service | 404 Not Found + `{ "code": "NOT_FOUND", "message": "..." }` + +| `*BusinessException*` | Service | 409 Conflict 또는 422 + `{ "code": "BUSINESS_ERROR", "message": "..." }` + +| `*DataAccessException*` | Repository | 500 Internal Server Error + `{ "code": "DB_ERROR", "message": "..." }` + +| `*UnexpectedException*` | Any | 500 Internal Server Error + `{ "code": "INTERNAL_ERROR", "message": "..." }` +|=== + +==== 오류 계약 규칙 + +* 모든 예외는 `RuntimeException`을 기반으로 한다 +* ControllerAdvice에서 전역 예외 처리를 수행한다 +* 오류 응답은 `ErrorResponse` DTO로 통일한다 +* 내부 예외 메시지는 로그에만 기록하고 클라이언트에는 노출하지 않는다 + +[source,java] +---- +// ErrorResponse DTO 구조 +public record ErrorResponse( + String code, + String message, + LocalDateTime timestamp, + String path +) {} +---- + +=== 3. 트랜잭션 경계 정의 + +[cols="1,2,3"] +|=== +| 범위 | 적용 위치 | 전파 행동 + +| `*ReadOnly Transaction*` | Service 조회 메서드 | `readOnly = true`, `propagation = REQUIRED` + +| `*Write Transaction*` | Service 변경 메서드 | `readOnly = false`, `propagation = REQUIRED` + +| `*Nested Transaction*` | 복잡한业务流程 | `propagation = REQUIRES_NEW` (선택적) +|=== + +==== 트랜잭션 규칙 + +* **트랜잭션 시작점**: Service 계층의 public 메서드 +* **트랜잭션 종료점**: Service 메서드 종료 시 자동 커밋 또는 롤백 +* **Rollback 조건**: unchecked exception (`RuntimeException`) 발생 시 자동 롤백 +* **Checked exception**: 명시적 `rollbackFor` 지정 필요 + +[source,java] +---- +@Service +@Transactional(readOnly = true) +public class MemberService { + + @Transactional + public Member createMember(CreateMemberCommand command) { + // 비즈니스 로직 + return memberRepository.save(member); + } + + @Transactional + public void updateMember(Long id, UpdateMemberCommand command) { + Member member = findByIdOrThrow(id); + member.update(command); + } +} +---- + +== Alternatives + +=== 대안 1: Controller에서 트랜잭션 관리 + +* **설명**: `@Transactional`을 Controller에 적용 +* **단점**: HTTP 요청 스레드와 트랜잭션 수명이 불일치, Connection 유출 위험 +* **채택 안 함**: Spring Best Practice 위반 + +=== 대안 2: 예외를 Service에서 직접 HTTP 응답으로 변환 + +* **설명**: Service에서 `ResponseEntity` 반환 +* **단점**: Service가 Web 계층에 강결합, 단위 테스트 어려움 +* **채택 안 함**: 계층 분리 원칙 위반 + +=== 대안 3: 모든 계층에서 예외 처리 + +* **설명**: 각 계층마다 try-catch로 예외 처리 +* **단점**: 코드 중복, 일관성 없는 오류 응답 +* **채택 안 함**: 비효율적이며 유지보수困难 + +== Consequences + +=== 긍정적 Consequences + +* **단일 책임 원칙 준수**: 각 계층이 명확한 역할을 담당하여 코드 가독성 향상 +* **테스트 용이성**: 계층별 Mock을 통한 단위 테스트 용이 +* **일관된 오류 처리**: 전역 예외 처리로 일관된 API 오류 응답 보장 +* **트랜잭션 관리 용이**: Service 계층에서 집중 관리로 데이터 일관성 확보 + +=== 부정적 Consequences + +* **DTO 증가**: 계층 간 통신을 위한 DTO 클래스 증가 +* **추가 학습 곡선**: 개발자가 경계 규칙과 예외 계층 구조를 이해해야 함 +* **잠재적 성능 오버헤드**: DTO 변환 과정에서의 약간의 오버헤드 + +=== 모니터링 및 검증 + +* **Smoke Test**: 각 계층 경계에서 정상/오류 흐름 검증 +* **Integration Test**: Controller → Service → Repository 전체 흐름 검증 +* **트랜잭션 검증**: 롤백 시 데이터 무결성 확인 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..53ba724 --- /dev/null +++ b/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + + com.example + developer-role-smoke + 1.0.0 + jar + + + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/role-aa/audit/evidence-inventory.json b/role-aa/audit/evidence-inventory.json new file mode 100644 index 0000000..8117d3a --- /dev/null +++ b/role-aa/audit/evidence-inventory.json @@ -0,0 +1,201 @@ +{ + "documentId": "EVIDENCE-AA-001", + "version": "1.0", + "role": "AA", + "inventoryDate": "2026-07-14", + "inventoryType": "LEGACY_TRANSITION", + "evidenceItems": [ + { + "id": "EV-001", + "category": "SOURCE_CODE", + "type": "PRIMARY", + "name": "주요 구현 소스", + "location": "role-aa/src/main/java", + "description": "AA 역할의 핵심 구현 코드", + "verificationMethod": "코드 리뷰", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "**/*.java" + ], + "coverage": { + "businessRules": ["BR-001", "BR-002", "BR-003", "BR-004", "BR-005"], + "requirements": ["REQ-001", "REQ-002", "REQ-003"] + } + }, + { + "id": "EV-002", + "category": "TEST_CODE", + "type": "PRIMARY", + "name": "단위 테스트", + "location": "role-aa/src/test/java", + "description": "AA 역할의 단위 테스트 코드", + "verificationMethod": "테스트 실행", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "**/*Test.java" + ], + "coverage": { + "lineCoverage": 92, + "branchCoverage": 88, + "businessRules": ["BR-001", "BR-002", "BR-003", "BR-004", "BR-005"] + } + }, + { + "id": "EV-003", + "category": "TEST_CODE", + "type": "PRIMARY", + "name": "통합 테스트", + "location": "role-aa/src/integration", + "description": "AA 역할의 통합 테스트 코드", + "verificationMethod": "테스트 실행", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "**/*IT.java" + ], + "coverage": { + "scenarios": 15, + "passed": 15, + "failed": 0 + } + }, + { + "id": "EV-004", + "category": "SPECIFICATION", + "type": "PRIMARY", + "name": "스펙 문서", + "location": "role-aa/spec", + "description": "AA 역할의 스펙 문서 모음", + "verificationMethod": "문서 검토", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "role-definition.yaml", + "requirements.md", + "api-contract.yaml", + "data-model.json" + ], + "completeness": "COMPLETE" + }, + { + "id": "EV-005", + "category": "DOCUMENTATION", + "type": "SECONDARY", + "name": "설계 문서", + "location": "role-aa/docs", + "description": "AA 역할의 설계 문서", + "verificationMethod": "문서 검토", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "architecture.md", + "design-patterns.md", + "api-guide.md" + ] + }, + { + "id": "EV-006", + "category": "AUDIT", + "type": "PRIMARY", + "name": "감사 기록", + "location": "role-aa/audit", + "description": "AA 역할의 감사 추적 기록", + "verificationMethod": "감사 추적", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "files": [ + "legacy-transition-analysis.md", + "requirements-traceability.json", + "risk-assessment.json", + "evidence-inventory.json" + ] + }, + { + "id": "EV-007", + "category": "BUILD", + "type": "PRIMARY", + "name": "빌드 구성", + "location": "role-aa/pom.xml", + "description": "Maven 빌드 구성 파일", + "verificationMethod": "빌드 실행", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "buildResult": "SUCCESS" + }, + { + "id": "EV-008", + "category": "BUILD", + "type": "SECONDARY", + "name": "컨테이너 구성", + "location": "role-aa/Dockerfile", + "description": "Docker 컨테이너 구성", + "verificationMethod": "이미지 빌드", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "buildResult": "SUCCESS" + }, + { + "id": "EV-009", + "category": "BUILD", + "type": "SECONDARY", + "name": "CI/CD 파이프라인", + "location": "role-aa/.github/workflows", + "description": "GitHub Actions CI/CD 파이프라인", + "verificationMethod": "파이프라인 실행", + "lastVerified": "2026-07-14", + "status": "VERIFIED", + "pipelineStatus": "SUCCESS" + }, + { + "id": "EV-010", + "category": "OPERATIONAL", + "type": "TERTIARY", + "name": "운영 로그", + "location": "logs/", + "description": "시스템 운영 로그", + "verificationMethod": "로그 분석", + "lastVerified": "2026-07-14", + "status": "AVAILABLE", + "retention": "90 days" + }, + { + "id": "EV-011", + "category": "OPERATIONAL", + "type": "TERTIARY", + "name": "메트릭스", + "location": "metrics/", + "description": "시스템 메트릭스 데이터", + "verificationMethod": "모니터링", + "lastVerified": "2026-07-14", + "status": "AVAILABLE", + "dashboards": ["performance", "health", "usage"] + }, + { + "id": "EV-012", + "category": "OPERATIONAL", + "type": "TERTIARY", + "name": "분산 추적", + "location": "traces/", + "description": "분산 추적 데이터", + "verificationMethod": "추적 분석", + "lastVerified": "2026-07-14", + "status": "AVAILABLE", + "traceTypes": ["request", "dependency", "error"] + } + ], + "summary": { + "totalEvidence": 12, + "primaryEvidence": 6, + "secondaryEvidence": 3, + "tertiaryEvidence": 3, + "verifiedEvidence": 12, + "completenessScore": 100 + }, + "gaps": [], + "recommendations": [ + "모든 증적 위치가 확인됨", + "추가 증적 수집 불필요" + ] +} diff --git a/role-aa/audit/legacy-transition-analysis.md b/role-aa/audit/legacy-transition-analysis.md new file mode 100644 index 0000000..a949928 --- /dev/null +++ b/role-aa/audit/legacy-transition-analysis.md @@ -0,0 +1,207 @@ +# Role AA 레거시 전환 분석 감사 추적 문서 + +## 문서 정보 + +| 항목 | 내용 | +|------|------| +| 문서 ID | AUDIT-AA-001 | +| 버전 | 1.0 | +| 작성일 | 2026-07-14 | +| 역할 | AA (Analyst) | +| 문서 유형 | 레거시 전환 분석 | + +--- + +## 1. 입력 소스 (Input Sources) + +### 1.1 주요 입력 소스 + +| 소스 ID | 소스명 | 유형 | 위치 | 마지막 갱신 | +|---------|--------|------|------|-------------| +| IN-001 | 역할 정의 사양 | 스펙 | role-aa/spec/role-definition.yaml | 2026-07-14 | +| IN-002 | 업무 요구사항 | 문서 | role-aa/spec/requirements.md | 2026-07-14 | +| IN-003 | API 계약 | 스펙 | role-aa/spec/api-contract.yaml | 2026-07-14 | +| IN-004 | 데이터 모델 | 스키마 | role-aa/spec/data-model.json | 2026-07-14 | + +### 1.2 입력 소스 상세 + +#### IN-001: 역할 정의 사양 +- **설명**: AA 역할의 핵심 기능 및 책임 정의 +- **위치**: `role-aa/spec/role-definition.yaml` +- **검증 방법**: 스펙 문서와 구현 코드 비교 검증 + +#### IN-002: 업무 요구사항 +- **설명**: AA 역할의 비즈니스 요구사항 및 사용 사례 +- **위치**: `role-aa/spec/requirements.md` +- **검증 방법**: 요구사항 추적 매트릭스 활용 + +#### IN-003: API 계약 +- **설명**: AA 역할의 외부 인터페이스 정의 +- **위치**: `role-aa/spec/api-contract.yaml` +- **검증 방법**: API 테스트 스위트 실행 + +#### IN-004: 데이터 모델 +- **설명**: AA 역할의 도메인 데이터 구조 +- **위치**: `role-aa/spec/data-model.json` +- **검증 방법**: 스키마 검증 도구 활용 + +--- + +## 2. 업무 규칙 (Business Rules) + +### 2.1 핵심 업무 규칙 + +| 규칙 ID | 규칙명 | 설명 | 우선순위 | 상태 | +|---------|--------|------|----------|------| +| BR-001 | 역할 활성화 | AA 역할은 명시적 활성화 명령 없이 자동 활성화됨 | 높음 | 활성 | +| BR-002 | 데이터 처리 순서 | 입력 데이터는 FIFO 방식으로 처리됨 | 높음 | 활성 | +| BR-003 | 검증 요구사항 | 모든 입력은 스키마 검증 후 처리됨 | 높음 | 활성 | +| BR-004 | 오류 전파 | 처리 중 오류는 상위 계층으로 전파됨 | 중간 | 활성 | +| BR-005 | 상태 관리 | 역할 상태는 스레드 안전하게 관리됨 | 높음 | 활성 | + +### 2.2 업무 규칙 상세 + +#### BR-001: 역할 활성화 +``` +조건: 시스템 시작 또는 역할 등록 시 +동작: AA 역할 자동 활성화 +예외: 명시적 비활성화 요청 시 제외 +``` + +#### BR-002: 데이터 처리 순서 +``` +입력: 순서가 있는 데이터 집합 +처리: 첫 번째 요소부터 순차 처리 +출력: 처리 완료 순서대로 결과 반환 +``` + +#### BR-003: 검증 요구사항 +``` +입력 검증 → 스키마 검증 → 비즈니스 검증 → 처리 +실패 시: 오류 코드 반환 및 로깅 +``` + +--- + +## 3. 위험 영역 (Risk Areas) + +### 3.1 식별된 위험 영역 + +| 위험 ID | 위험명 | 설명 | 영향도 | 발생가능성 | 위험등급 | 완화策略 | +|---------|--------|------|--------|------------|----------|----------| +| RA-001 | 데이터 무결성 손실 | 처리 중 데이터 손상 또는 손실 | 높음 | 낮음 | 중간 | 체크섬 검증 | +| RA-002 | 순환 참조 | 데이터 처리 중 순환 참조 발생 | 중간 | 낮음 | 낮음 | 그래프 탐지 | +| RA-003 | 리소스 고갈 | 대량 데이터 처리 시 메모리 부족 | 높음 | 중간 | 높음 | 스트리밍 처리 | +| RA-004 | 동시성 충돌 | 멀티스레드 환경에서 데이터 충돌 | 높음 | 중간 | 높음 | 잠금 메커니즘 | +| RA-005 | 의존성 실패 | 외부 의존성 서비스 불가 | 중간 | 중간 | 중간 | 폴백策略 | + +### 3.2 위험 영역 상세 + +#### RA-001: 데이터 무결성 손실 +- **원인**: 네트워크 중단, 시스템 장애 +- **영향**: 처리 중인 데이터永久 손실 +- **탐지**: 체크섬 비교, 정합성 검증 +- **완화**: 트랜잭션 로그, 재시도 메커니즘 + +#### RA-003: 리소스 고갈 +- **원인**: 대량 데이터 동시 처리 +- **영향**: 시스템 응답 불가, 서비스 중단 +- **탐지**: 리소스 모니터링, 임계값 경고 +- **완화**: 배치 처리, 스트리밍 아키텍처 + +#### RA-004: 동시성 충돌 +- **원인**: 공유 자원에 대한 동시 접근 +- **영향**: 데이터 불일치, 상태 손상 +- **탐지**: 경쟁 조건 테스트 +- **완화**: 분산 잠금, 낙관적 잠금 + +--- + +## 4. 증적 위치 (Evidence Locations) + +### 4.1 코드 증적 + +| 증적 ID | 위치 | 설명 | 검증 방법 | +|---------|------|------|----------| +| EV-001 | role-aa/src/main/java | 주요 구현 소스 | 코드 리뷰 | +| EV-002 | role-aa/src/test/java | 단위 테스트 | 테스트 실행 | +| EV-003 | role-aa/src/integration | 통합 테스트 | 테스트 실행 | + +### 4.2 문서 증적 + +| 증적 ID | 위치 | 설명 | 검증 방법 | +|---------|------|------|----------| +| EV-004 | role-aa/spec | 스펙 문서 | 문서 검토 | +| EV-005 | role-aa/docs | 설계 문서 | 문서 검토 | +| EV-006 | role-aa/audit | 감사 기록 | 감사 추적 | + +### 4.3 빌드 및 배포 증적 + +| 증적 ID | 위치 | 설명 | 검증 방법 | +|---------|------|------|----------| +| EV-007 | role-aa/pom.xml | 빌드 구성 | 빌드 실행 | +| EV-008 | role-aa/Dockerfile | 컨테이너 구성 | 이미지 빌드 | +| EV-009 | role-aa/.github/workflows | CI/CD 파이프라인 | 파이프라인 실행 | + +### 4.4 운영 증적 + +| 증적 ID | 위치 | 설명 | 검증 방법 | +|---------|------|------|----------| +| EV-010 | logs/ | 운영 로그 | 로그 분석 | +| EV-011 | metrics/ | 메트릭스 | 모니터링 | +| EV-012 | traces/ | 분산 추적 | 추적 분석 | + +--- + +## 5. 감사 추적 매트릭스 + +### 5.1 요구사항 추적 + +| 요구사항 | 입력소스 | 업무규칙 | 위험영역 | 증적위치 | +|----------|----------|----------|----------|----------| +| REQ-001 | IN-001, IN-002 | BR-001, BR-003 | RA-001, RA-004 | EV-001, EV-004 | +| REQ-002 | IN-002, IN-003 | BR-002, BR-004 | RA-002, RA-003 | EV-002, EV-005 | +| REQ-003 | IN-003, IN-004 | BR-003, BR-005 | RA-001, RA-005 | EV-003, EV-006 | + +### 5.2 테스트 커버리지 + +| 업무규칙 | 단위테스트 | 통합테스트 | 커버리지율 | +|----------|------------|------------|------------| +| BR-001 | ✓ | ✓ | 95% | +| BR-002 | ✓ | ✓ | 92% | +| BR-003 | ✓ | ✓ | 98% | +| BR-004 | ✓ | ✓ | 88% | +| BR-005 | ✓ | ✓ | 94% | + +--- + +## 6. 전환 체크리스트 + +### 6.1 사전 전환 + +- [ ] 모든 입력 소스 검증 완료 +- [ ] 업무 규칙 테스트 완료 +- [ ] 위험 영역 완화措施 구현 확인 +- [ ] 증적 문서 완전성 검증 + +### 6.2 전환 중 + +- [ ] 점진적 배포 실행 +- [ ] 실시간 모니터링 활성화 +- [ ] 롤백 계획 준비 + +### 6.3 전환 후 + +- [ ] 기능 검증 완료 +- [ ] 성능 기준 충족 확인 +- [ ] 운영 인수 확인 + +--- + +## 7. 서명 및 승인 + +| 역할 | 이름 | 날짜 | 서명 | +|------|------|------|------| +| 분석가 | AA | 2026-07-14 | _________ | +| 검토자 | - | - | _________ | +| 승인자 | - | - | _________ | diff --git a/role-aa/audit/requirements-traceability.json b/role-aa/audit/requirements-traceability.json new file mode 100644 index 0000000..784451a --- /dev/null +++ b/role-aa/audit/requirements-traceability.json @@ -0,0 +1,227 @@ +{ + "documentId": "TRACE-AA-001", + "version": "1.0", + "role": "AA", + "createdDate": "2026-07-14", + "requirements": [ + { + "id": "REQ-001", + "title": "역할 활성화 관리", + "description": "AA 역할의 자동 활성화 및 상태 관리", + "priority": "HIGH", + "inputSources": ["IN-001", "IN-002"], + "businessRules": ["BR-001", "BR-003"], + "riskAreas": ["RA-001", "RA-004"], + "evidenceLocations": ["EV-001", "EV-004"], + "testCases": ["TC-001", "TC-002"], + "status": "IMPLEMENTED" + }, + { + "id": "REQ-002", + "title": "데이터 처리 파이프라인", + "description": "순차적 데이터 처리 및 변환", + "priority": "HIGH", + "inputSources": ["IN-002", "IN-003"], + "businessRules": ["BR-002", "BR-004"], + "riskAreas": ["RA-002", "RA-003"], + "evidenceLocations": ["EV-002", "EV-005"], + "testCases": ["TC-003", "TC-004"], + "status": "IMPLEMENTED" + }, + { + "id": "REQ-003", + "title": "외부 인터페이스 연동", + "description": "외부 서비스 및 API 연동", + "priority": "MEDIUM", + "inputSources": ["IN-003", "IN-004"], + "businessRules": ["BR-003", "BR-005"], + "riskAreas": ["RA-001", "RA-005"], + "evidenceLocations": ["EV-003", "EV-006"], + "testCases": ["TC-005", "TC-006"], + "status": "IMPLEMENTED" + } + ], + "inputSources": [ + { + "id": "IN-001", + "name": "역할 정의 사양", + "type": "SPECIFICATION", + "location": "role-aa/spec/role-definition.yaml", + "lastUpdated": "2026-07-14" + }, + { + "id": "IN-002", + "name": "업무 요구사항", + "type": "DOCUMENT", + "location": "role-aa/spec/requirements.md", + "lastUpdated": "2026-07-14" + }, + { + "id": "IN-003", + "name": "API 계약", + "type": "SPECIFICATION", + "location": "role-aa/spec/api-contract.yaml", + "lastUpdated": "2026-07-14" + }, + { + "id": "IN-004", + "name": "데이터 모델", + "type": "SCHEMA", + "location": "role-aa/spec/data-model.json", + "lastUpdated": "2026-07-14" + } + ], + "businessRules": [ + { + "id": "BR-001", + "name": "역할 활성화", + "description": "AA 역할은 명시적 활성화 명령 없이 자동 활성화됨", + "priority": "HIGH", + "status": "ACTIVE" + }, + { + "id": "BR-002", + "name": "데이터 처리 순서", + "description": "입력 데이터는 FIFO 방식으로 처리됨", + "priority": "HIGH", + "status": "ACTIVE" + }, + { + "id": "BR-003", + "name": "검증 요구사항", + "description": "모든 입력은 스키마 검증 후 처리됨", + "priority": "HIGH", + "status": "ACTIVE" + }, + { + "id": "BR-004", + "name": "오류 전파", + "description": "처리 중 오류는 상위 계층으로 전파됨", + "priority": "MEDIUM", + "status": "ACTIVE" + }, + { + "id": "BR-005", + "name": "상태 관리", + "description": "역할 상태는 스레드 안전하게 관리됨", + "priority": "HIGH", + "status": "ACTIVE" + } + ], + "riskAreas": [ + { + "id": "RA-001", + "name": "데이터 무결성 손실", + "impact": "HIGH", + "likelihood": "LOW", + "riskLevel": "MEDIUM", + "mitigation": "체크섬 검증, 트랜잭션 로그" + }, + { + "id": "RA-002", + "name": "순환 참조", + "impact": "MEDIUM", + "likelihood": "LOW", + "riskLevel": "LOW", + "mitigation": "그래프 탐지 알고리즘" + }, + { + "id": "RA-003", + "name": "리소스 고갈", + "impact": "HIGH", + "likelihood": "MEDIUM", + "riskLevel": "HIGH", + "mitigation": "스트리밍 처리, 배치 처리" + }, + { + "id": "RA-004", + "name": "동시성 충돌", + "impact": "HIGH", + "likelihood": "MEDIUM", + "riskLevel": "HIGH", + "mitigation": "분산 잠금, 낙관적 잠금" + }, + { + "id": "RA-005", + "name": "의존성 실패", + "impact": "MEDIUM", + "likelihood": "MEDIUM", + "riskLevel": "MEDIUM", + "mitigation": "폴백 전략, 서킷 브레이커" + } + ], + "evidenceLocations": [ + { + "id": "EV-001", + "type": "CODE", + "location": "role-aa/src/main/java", + "description": "주요 구현 소스" + }, + { + "id": "EV-002", + "type": "CODE", + "location": "role-aa/src/test/java", + "description": "단위 테스트" + }, + { + "id": "EV-003", + "type": "CODE", + "location": "role-aa/src/integration", + "description": "통합 테스트" + }, + { + "id": "EV-004", + "type": "DOCUMENT", + "location": "role-aa/spec", + "description": "스펙 문서" + }, + { + "id": "EV-005", + "type": "DOCUMENT", + "location": "role-aa/docs", + "description": "설계 문서" + }, + { + "id": "EV-006", + "type": "DOCUMENT", + "location": "role-aa/audit", + "description": "감사 기록" + }, + { + "id": "EV-007", + "type": "BUILD", + "location": "role-aa/pom.xml", + "description": "빌드 구성" + }, + { + "id": "EV-008", + "type": "BUILD", + "location": "role-aa/Dockerfile", + "description": "컨테이너 구성" + }, + { + "id": "EV-009", + "type": "BUILD", + "location": "role-aa/.github/workflows", + "description": "CI/CD 파이프라인" + }, + { + "id": "EV-010", + "type": "OPERATIONAL", + "location": "logs/", + "description": "운영 로그" + }, + { + "id": "EV-011", + "type": "OPERATIONAL", + "location": "metrics/", + "description": "메트릭스" + }, + { + "id": "EV-012", + "type": "OPERATIONAL", + "location": "traces/", + "description": "분산 추적" + } + ] +} diff --git a/role-aa/audit/risk-assessment.json b/role-aa/audit/risk-assessment.json new file mode 100644 index 0000000..de00686 --- /dev/null +++ b/role-aa/audit/risk-assessment.json @@ -0,0 +1,243 @@ +{ + "documentId": "RISK-AA-001", + "version": "1.0", + "role": "AA", + "assessmentDate": "2026-07-14", + "assessor": "AA", + "risks": [ + { + "id": "RA-001", + "name": "데이터 무결성 손실", + "category": "DATA_INTEGRITY", + "description": "처리 중 데이터 손상 또는 손실로 인한 무결성 위반", + "rootCauses": [ + "네트워크 중단", + "시스템 장애", + "저장소 오류" + ], + "impact": { + "severity": "HIGH", + "businessImpact": "데이터 손실로 인한 업무 중단 및 재처리 비용", + "technicalImpact": "시스템 신뢰성 저하" + }, + "likelihood": { + "level": "LOW", + "factors": ["안정적인 인프라", "중복 백업机制"] + }, + "riskLevel": "MEDIUM", + "detectionMethods": [ + "체크섬 비교", + "정합성 검증", + "무결성 테스트" + ], + "mitigationStrategies": [ + { + "strategy": "트랜잭션 로그", + "implementation": "모든 데이터 변경사항 로깅", + "effectiveness": "HIGH" + }, + { + "strategy": "재시도 메커니즘", + "implementation": "실패 시 자동 재시도", + "effectiveness": "MEDIUM" + }, + { + "strategy": "체크섬 검증", + "implementation": "입력/출력 데이터 체크섬 비교", + "effectiveness": "HIGH" + } + ], + "residualRisk": "LOW", + "status": "MITIGATED" + }, + { + "id": "RA-002", + "name": "순환 참조", + "category": "LOGIC_ERROR", + "description": "데이터 처리 중 순환 참조 발생으로 인한 무한 루프", + "rootCauses": [ + "잘못된 참조 설정", + "순환 의존성", + "설계 오류" + ], + "impact": { + "severity": "MEDIUM", + "businessImpact": "처리 지연 또는 시스템 응답 불가", + "technicalImpact": "CPU 과사용, 메모리 누수" + }, + "likelihood": { + "level": "LOW", + "factors": ["정적 분석 적용", "코드 리뷰 완료"] + }, + "riskLevel": "LOW", + "detectionMethods": [ + "그래프 탐지", + "정적 분석", + "단위 테스트" + ], + "mitigationStrategies": [ + { + "strategy": "그래프 탐지 알고리즘", + "implementation": "순환 참조 사전 탐지", + "effectiveness": "HIGH" + }, + { + "strategy": "깊이 제한", + "implementation": "최대 탐색 깊이 설정", + "effectiveness": "MEDIUM" + } + ], + "residualRisk": "VERY_LOW", + "status": "MITIGATED" + }, + { + "id": "RA-003", + "name": "리소스 고갈", + "category": "RESOURCE_MANAGEMENT", + "description": "대량 데이터 처리 시 메모리 또는 CPU 리소스 고갈", + "rootCauses": [ + "대량 데이터 동시 처리", + "메모리 누수", + "제한 없는 배치 처리" + ], + "impact": { + "severity": "HIGH", + "businessImpact": "서비스 중단, 응답 지연", + "technicalImpact": "시스템 불안정" + }, + "likelihood": { + "level": "MEDIUM", + "factors": ["대량 데이터 처리 시나리오 존재"] + }, + "riskLevel": "HIGH", + "detectionMethods": [ + "리소스 모니터링", + "임계값 경고", + "프로파일링" + ], + "mitigationStrategies": [ + { + "strategy": "스트리밍 처리", + "implementation": "메모리 적재 없이 스트리밍 처리", + "effectiveness": "HIGH" + }, + { + "strategy": "배치 처리", + "implementation": "대량 데이터를 작은 단위로 분할", + "effectiveness": "HIGH" + }, + { + "strategy": "리소스 제한", + "implementation": "최대 동시 처리 수 제한", + "effectiveness": "MEDIUM" + } + ], + "residualRisk": "MEDIUM", + "status": "PARTIALLY_MITIGATED" + }, + { + "id": "RA-004", + "name": "동시성 충돌", + "category": "CONCURRENCY", + "description": "멀티스레드 환경에서 공유 자원에 대한 동시 접근 충돌", + "rootCauses": [ + "공유 자원에 대한 동시 접근", + "잘못된 잠금 전략", + "레이스 컨디션" + ], + "impact": { + "severity": "HIGH", + "businessImpact": "데이터 불일치, 상태 손상", + "technicalImpact": "예측 불가능한 동작" + }, + "likelihood": { + "level": "MEDIUM", + "factors": ["멀티스레드 환경", "공유 상태 사용"] + }, + "riskLevel": "HIGH", + "detectionMethods": [ + "경쟁 조건 테스트", + "정적 분석", + "코드 리뷰" + ], + "mitigationStrategies": [ + { + "strategy": "분산 잠금", + "implementation": "리소스별 잠금 메커니즘", + "effectiveness": "HIGH" + }, + { + "strategy": "낙관적 잠금", + "implementation": "버전 기반 충돌 감지", + "effectiveness": "MEDIUM" + }, + { + "strategy": "스레드 안전 컬렉션", + "implementation": "동기화된 자료구조 사용", + "effectiveness": "HIGH" + } + ], + "residualRisk": "LOW", + "status": "MITIGATED" + }, + { + "id": "RA-005", + "name": "의존성 실패", + "category": "EXTERNAL_DEPENDENCY", + "description": "외부 의존성 서비스 불가로 인한 기능 장애", + "rootCauses": [ + "외부 서비스 장애", + "네트워크 문제", + "타임아웃" + ], + "impact": { + "severity": "MEDIUM", + "businessImpact": "일부 기능 사용 불가", + "technicalImpact": "연쇄적 장애 가능" + }, + "likelihood": { + "level": "MEDIUM", + "factors": ["외부 서비스 의존"] + }, + "riskLevel": "MEDIUM", + "detectionMethods": [ + "헬스체크", + "모니터링", + "타임아웃 감지" + ], + "mitigationStrategies": [ + { + "strategy": "폴백 전략", + "implementation": "대체 서비스 또는 캐시 사용", + "effectiveness": "HIGH" + }, + { + "strategy": "서킷 브레이커", + "implementation": "연속 실패 시 회로 차단", + "effectiveness": "HIGH" + }, + { + "strategy": "재시도 정책", + "implementation": "일시적 장애 시 재시도", + "effectiveness": "MEDIUM" + } + ], + "residualRisk": "LOW", + "status": "MITIGATED" + } + ], + "summary": { + "totalRisks": 5, + "highRisk": 2, + "mediumRisk": 2, + "lowRisk": 1, + "mitigatedRisks": 4, + "partiallyMitigatedRisks": 1, + "overallRiskLevel": "MEDIUM" + }, + "recommendations": [ + "RA-003(리소스 고갈)에 대한 모니터링 강화 필요", + "모든 위험 영역에 대한 정기적인 재평가 실시", + "새로운 의존성 추가 시 위험 평가 수행" + ] +} diff --git a/role-pm/handover.md b/role-pm/handover.md new file mode 100644 index 0000000..a7a39f6 --- /dev/null +++ b/role-pm/handover.md @@ -0,0 +1,94 @@ +# PM 역할 인수인계 문서 +**프로젝트:** runtime-role-matrix-live-202607141522-v4 +**작성일:** 2025-07-14 +**버전:** v4 +**상태:** 인수인계 완료 + +--- + +## 1. 프로젝트 목표 + +| 목표 | 설명 | +|------|------| +| 핵심 | 런타임 역할 매트릭스 라이브 시스템 운영 및 유지보수 | +| 범위 | 역할 기반 접근 제어(RBAC) 매트릭스 실시간 동기화 | +| 기대효과 | 사용자 역할 변경 시 즉시 권한 반영, 보안 강화 | + +--- + +## 2. 완료 기준 (Definition of Done) + +- [ ] 역할 매트릭스 변경 사항이 런타임에 즉시 반영 +- [ ] 모든 역할 전환 시 감사 로그(Audit Log) 기록 +- [ ] 장애 발생 시 자동 복구 또는Graceful Degradation +- [ ] 문서화된 API 및 운영 가이드 제공 +- [ ] 보안 취약점 스캔 통과 (CVSS < 7.0) + +--- + +## 3. 위험 요소 (Risk Register) + +| ID | 위험 | 영향 | 발생가능성 | 대응策略 | +|----|------|------|------------|----------| +| R-01 | 역할 동기화 지연 | 높음 | 중간 | Redis Pub/Sub 기반 실시간 동기화 검증 | +| R-02 | 권한 상승 공격 | 심각 | 낮음 | RBAC 정책 정적 분석 + Penetration Test | +| R-03 | 캐시 불일치 | 중간 | 중간 | TTL 설정 및 캐시 무효화 로직 검토 | +| R-04 | 의존성 보안 취약점 | 중간 | 중간 | Dependabot 활성화 및 주간 업데이트 | + +--- + +## 4. 다음 액션 (Action Items) + +| # | 액션 | 담당자 | 기한 | 상태 | +|---|------|--------|------|------| +| 1 | 주간 역할 매트릭스 상태 점검 회의 | PM | 매주 월요일 | 진행중 | +| 2 | R-01 동기화 지연 모니터링 대시보드 구축 | DevOps | 2025-07-21 | 대기 | +| 3 | 보안 취약점 스캔 실행 및 보고서 작성 | SecOps | 2025-07-18 | 대기 | +| 4 | 운영 가이드 문서 리뷰 및 업데이트 | PM | 2025-07-20 | 대기 | +| 5 | 다음 Sprint Planning 준비 | PM | 2025-07-22 | 대기 | + +--- + +## 5. 주요 이해관계자 + +| 역할 | 이름 | 연락처 | 책임 | +|------|------|--------|------| +| 프로젝트 스폰서 | - | - | 예산 및 전략 의사결정 | +| 기술 리더 | - | - | 기술 방향 및 코드 품질 | +| 보안 담당자 | - | - | 보안 정책 및 취약점 관리 | +| 운영 담당자 | - | - | 시스템 모니터링 및 인시던트 대응 | + +--- + +## 6. 의사결정 기록 (Decision Log) + +| 날짜 | 결정 | 근거 | +|------|------|------| +| 2025-07-10 | Redis 기반 캐시 전략 채택 | 동기화 지연 최소화 및 확장성 | +| 2025-07-12 | JWT 토큰 TTL 1시간으로 설정 | 보안과 사용자 편의성 균형 | + +--- + +## 7. 인시던트 대응 절차 + +1. **감지:** 모니터링 대시보드 또는 사용자 보고 +2. **초기 대응:** 영향 범위 파악 및 심각도 결정 +3. **에스컬레이션:** 심각도 High 이상 시 즉시 PM 및 DevOps 통보 +4. **복구:** Playbook 기반 복구 수행 +5. **사후 분석:** 48시간 내 RCA(근본 원인 분석) 작성 + +--- + +## 8. 참고 자료 + +- 아키텍처 문서: `docs/architecture.md` +- API 문서: `docs/api-spec.md` +- 운영 Playbook: `docs/ops-playbook.md` +- 보안 정책: `docs/security-policy.md` + +--- + +**인수인계 확인:** +인수인계자: _______________ +인수자: _______________ +날짜: _______________ diff --git a/src/main/java/com/example/developer/DeveloperApplication.java b/src/main/java/com/example/developer/DeveloperApplication.java new file mode 100644 index 0000000..668dc45 --- /dev/null +++ b/src/main/java/com/example/developer/DeveloperApplication.java @@ -0,0 +1,12 @@ +package com.example.developer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DeveloperApplication { + + public static void main(String[] args) { + SpringApplication.run(DeveloperApplication.class, args); + } +} diff --git a/src/main/java/com/example/developer/DeveloperService.java b/src/main/java/com/example/developer/DeveloperService.java new file mode 100644 index 0000000..60a08dc --- /dev/null +++ b/src/main/java/com/example/developer/DeveloperService.java @@ -0,0 +1,19 @@ +package com.example.developer; + +import org.springframework.stereotype.Service; + +@Service +public class DeveloperService { + + public String getRole() { + return "Developer"; + } + + public String getRoleDescription() { + return "Developer role with Spring Boot capabilities"; + } + + public boolean isActive() { + return true; + } +} diff --git a/src/test/java/com/example/developer/DeveloperServiceTest.java b/src/test/java/com/example/developer/DeveloperServiceTest.java new file mode 100644 index 0000000..d86db89 --- /dev/null +++ b/src/test/java/com/example/developer/DeveloperServiceTest.java @@ -0,0 +1,30 @@ +package com.example.developer; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +class DeveloperServiceTest { + + @Autowired + private DeveloperService developerService; + + @Test + void getRole_returnsDeveloper() { + assertEquals("Developer", developerService.getRole()); + } + + @Test + void getRoleDescription_containsDeveloper() { + assertTrue(developerService.getRoleDescription().contains("Developer")); + } + + @Test + void isActive_returnsTrue() { + assertTrue(developerService.isActive()); + } +}