TA 역할 Spring 경계 smoke (role-ta-live-v2-001)
All checks were successful
ci / test (pull_request) Successful in 1m42s
All checks were successful
ci / test (pull_request) Successful in 1m42s
This commit is contained in:
parent
bdce7117cf
commit
927cc8b5d9
1 changed files with 99 additions and 0 deletions
99
docs/adr/ADR-001-spring-boundary-contract.md
Normal file
99
docs/adr/ADR-001-spring-boundary-contract.md
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# ADR-001: Spring 계층 경계, 오류 계약 및 트랜잭션 경계 정의
|
||||
|
||||
**날짜:** 2026-07-14
|
||||
**상태:** 수락됨
|
||||
**결정자:** TA 아키텍트
|
||||
|
||||
---
|
||||
|
||||
## Context (맥락)
|
||||
|
||||
`runtime-role-matrix-live-202607141522-v2` 프로젝트는 Spring Boot 기반 멀티 모듈 애플리케이션이다.
|
||||
현재 계층 간 책임 범위가 모호하고, 예외 처리 정책이 불명확하며, 트랜잭션 전파 규칙이 문서화되지 않아
|
||||
유지보수성과 일관성에 위험이 존재한다.
|
||||
|
||||
---
|
||||
|
||||
## Decision (결정)
|
||||
|
||||
### 1. Controller-Service-Repository 경계
|
||||
|
||||
| 계층 | 책임 | 허용 작업 |
|
||||
|------|------|-----------|
|
||||
| **Controller** | HTTP 요청/응답 변환, 입력 검증, HTTP 상태 코드 결정 | `@Valid`, `@RequestBody`, `@PathVariable` 파싱, Service 호출, `ResponseEntity` 반환 |
|
||||
| **Service** | 비즈니스 로직, 도메인 규칙, 트랜잭션 경계 | Repository 호출, 도메인 객체 조작, 다른 Service 호출 (필요시), `@Transactional` 적용 |
|
||||
| **Repository** | 데이터 접근 추상화, 쿼리 실행 | JPA `CrudRepository`/`JpaRepository` 메서드, `@Query`, `EntityManager` 직접 사용 |
|
||||
|
||||
**금지 규칙:**
|
||||
- Controller는 `@Transactional`을 직접 적용하지 않는다.
|
||||
- Repository는 비즈니스 로직을 포함하지 않는다.
|
||||
- Service 계층을 건너뛰고 Controller가 Repository를 직접 호출하지 않는다.
|
||||
|
||||
### 2. 오류 계약 (Error Contract)
|
||||
|
||||
모든 계층에서 발생하는 예외는 다음 규칙을 따른다.
|
||||
|
||||
| 예외 유형 | 발생 계층 | HTTP 상태 | 응답 본문 필드 |
|
||||
|----------|-----------|-----------|---------------|
|
||||
| `ValidationException` | Controller | 400 | `{ "code": "VALIDATION_ERROR", "message": "...", "field": "..." }` |
|
||||
| `ResourceNotFoundException` | Service/Repository | 404 | `{ "code": "NOT_FOUND", "message": "...", "resourceId": "..." }` |
|
||||
| `BusinessRuleViolationException` | Service | 409 | `{ "code": "BUSINESS_RULE_VIOLATION", "message": "...", "rule": "..." }` |
|
||||
| `DataAccessException` | Repository | 500 | `{ "code": "DATABASE_ERROR", "message": "Internal server error" }` |
|
||||
| `UnexpectedException` | Any | 500 | `{ "code": "INTERNAL_ERROR", "message": "Internal server error" }` |
|
||||
|
||||
**오류 계약 규칙:**
|
||||
- ControllerAdvice가 모든 예외를 가로채고 일관된 JSON 구조로 변환한다.
|
||||
- 내부 예외 메시지는 클라이언트에 노출하지 않는다 (로그에만 기록).
|
||||
- 예외 계층 구조: `RuntimeException` → `BaseException` → 구체 예외 클래스.
|
||||
|
||||
### 3. 트랜잭션 경계
|
||||
|
||||
| 시나리오 | 전파 방식 | 격리 수준 | 롤백 규칙 |
|
||||
|---------|-----------|-----------|-----------|
|
||||
| Service → Repository 호출 | `REQUIRED` (기본) | `READ_COMMITTED` (기본) | Checked 예외는 롤백하지 않음, Unchecked 예외는 롤백 |
|
||||
| readOnly 트랜잭션 | `REQUIRED` + `readOnly=true` | `READ_COMMITTED` | 읽기 전용, 쓰기 시 예외 발생 |
|
||||
| 다중 Service 호출 (같은 트랜잭션) | `REQUIRED` | 상속됨 | 부모 트랜잭션과 동일하게 처리 |
|
||||
| 별도 트랜잭션 필요 | `REQUIRES_NEW` | 명시적 지정 | 독립 롤백 가능 |
|
||||
|
||||
**트랜잭션 규칙:**
|
||||
- `@Transactional`은 public 메서드에만 적용한다.
|
||||
- 클래스 레벨 `@Transactional`보다 메서드 레벨이 우선한다.
|
||||
- `readOnly=true`는 SELECT 성능 최적화를 위해 명시적으로 설정한다.
|
||||
|
||||
---
|
||||
|
||||
## Alternatives (대안)
|
||||
|
||||
### 대안 1: DTO 직접 전달 방식
|
||||
Controller가 Entity를 직접 Service에 전달하고 Service가 Entity를 직접 반환한다.
|
||||
- **단점:** 계층 간 결합도 증가, 테스트 어려움, 도메인 오염 위험.
|
||||
- **선택하지 않음**
|
||||
|
||||
### 대안 2: 전역 예외 처리 미사용
|
||||
각 Controller에서 개별적으로 예외를 처리한다.
|
||||
- **단점:** 코드 중복, 응답 형식 불일치, 유지보수 비용 증가.
|
||||
- **선택하지 않음**
|
||||
|
||||
### 대안 3: Programmatic Transaction
|
||||
`TransactionTemplate`을 사용하여 명시적으로 트랜잭션을 관리한다.
|
||||
- **단점:** 선언적 트랜잭션 대비 코드 복잡, 실수 가능성 증가.
|
||||
- **선택하지 않음**
|
||||
|
||||
---
|
||||
|
||||
## Consequences (결과)
|
||||
|
||||
### 긍정적 결과
|
||||
- 계층별 책임이 명확해져 개발자 간 협업 효율 향상
|
||||
- 일관된 오류 응답으로 API 소비자가 예측 가능한 에러 처리 가능
|
||||
- 선언적 트랜잭션으로 데이터 무결성 보장
|
||||
|
||||
### 부정적 결과
|
||||
- DTO 변환 코드가 추가됨 (Mapper 또는 수동 변환)
|
||||
- 예외 계층 구조 도입으로 초기 개발 시간 증가
|
||||
- `readOnly` 설정 누락 시 성능 최적화 미적용
|
||||
|
||||
### 모니터링 필요 항목
|
||||
- Controller 레벨 HTTP 5xx 에러율
|
||||
- Service 레벨 트랜잭션 롤백 빈도
|
||||
- Repository 레벨 쿼리 성능 (N+1 문제)
|
||||
Loading…
Add table
Add a link
Reference in a new issue