Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ kubectl apply -k k8s/overlays/prod-k8s # 서비스 + HPA + PDB
- **Kafka 토픽** → `docs/architecture/kafka-convention.md`
- **API 응답 포맷**: `ApiResponse<T>` → `docs/architecture/api-response.md`
- **Common 기능 로드**: Auto-Configuration (`kgd.common.*`) → `docs/architecture/common-features.md`
- **코드 생성 컨벤션**: 네이밍, DI 방향, 도메인 패턴 → `docs/adr/ADR-0014-code-convention.md`
- **코드 생성 컨벤션**: 네이밍, DI 방향, 도메인 패턴 → `docs/conventions/code-convention.md`
- **멱등성 패턴**: Kafka Consumer 중복 처리 방어 → `docs/adr/ADR-0012-idempotent-consumer.md`
- **장애 대비 전략**: CircuitBreaker, DLQ, Rate Limiting, CQRS → `docs/adr/ADR-0015-resilience-strategy.md`
- **백업/복구**: XtraBackup + Binlog PITR → `docker/backup/README.md` (스크립트) · `k8s/infra/prod/backup/` (CronJob 래퍼)
- **K8s 전환**: 배포 모드 이원화, Eureka 제거, Jib → `docs/adr/ADR-0019-k8s-migration.md`
- **FE 디자인 가드레일**: AI slop 방지, 타이포/색상/레이아웃/모션/접근성 → `docs/conventions/frontend-design.md`
- **@Transactional 규칙**: 외부 IO 분리, 중첩 txn 예외 금지, 클래스 레벨 주의 → `docs/adr/ADR-0020-transactional-usage.md`
- **로깅 규칙**: kotlin-logging 필수, 람다 형식, error 레벨 규칙 → `docs/adr/ADR-0021-logging-conventions.md`
- **로깅 규칙**: kotlin-logging 필수, 람다 형식, error 레벨 규칙 → `docs/conventions/logging.md`
- **Entity 수정 규칙**: 전체 동기화 vs 부분 수정 분리, 캡슐화 → `docs/adr/ADR-0022-entity-mutation-conventions.md`
- **문서-소스 추적**: `doc_map.py` / `doc_scan.py`, `docs/doc-index.json` 정책, `docs/doc-index.lock.json` 검증 → `docs/adr/ADR-0023-doc-index-tracking.md`
- **문서-소스 추적**: `doc_map.py` / `doc_scan.py`, `docs/doc-index.json` 정책, `docs/doc-index.lock.json` 검증 → `docs/standards/doc-index-tracking.md`
- **Latency Budget**: latency 를 설계 입력으로 강제 + Tier 1 P99 SLA + 측정 표준 → `docs/adr/ADR-0025-latency-budget.md` (실천: `docs/conventions/latency-budget.md`)
- **docs 분류 정책**: ADR vs Conventions vs Standards 의 정의 / 판단 기준 / 분해 원칙 / redirect 표준 → `docs/adr/ADR-0026-docs-taxonomy.md`

Expand Down
183 changes: 10 additions & 173 deletions docs/adr/ADR-0014-code-convention.md
Original file line number Diff line number Diff line change
@@ -1,184 +1,21 @@
# ADR-0014 Code Convention 통합 레퍼런스
# ADR-0014 [Moved] Code Convention 통합 레퍼런스

## Status
Accepted

## Context
Moved (재분류) — 2026-04-26

프로젝트 전반의 코드 생성 컨벤션이 여러 문서에 분산되어 있어,
새로운 서비스/모듈 추가 시 일관성을 유지하기 어렵다. 기존 코드에서 추출한 실제 패턴과 문서화된 규칙을 통합하여 단일 레퍼런스를 제공한다.
## 새 위치

**기존 문서 참조 관계:**
- 아키텍처 원칙: `docs/architecture/00.clean-architecture.md`
- 패키지 구조: `docs/conventions/package-structure.md`
- 테스트 규칙: `docs/standards/test-rules.md`
- Kafka 컨벤션: `docs/architecture/kafka-convention.md`
- API 응답 포맷: `docs/conventions/api-format.md`
`docs/conventions/code-convention.md`

이 ADR은 위 문서에서 다루지 않는 **네이밍, DI 방향, 클래스 역할 정의**를 보완한다.
## 이동 사유

## Decision
코드 작성 규칙 (네이밍 / DI 방향 / 도메인 패턴 / 매핑 패턴) 으로, ADR-0026 분류 기준상 **architecturally significant decision 이 아닌 convention** 으로 판정. 코드 리뷰 베이스라인이라 conventions/ 가 본질적 위치.

### 1. 클래스 네이밍 컨벤션
## History

| 레이어 | 컴포넌트 | 네이밍 패턴 | 예시 |
|--------|---------|------------|------|
| **Domain** | Aggregate/Entity | `{Entity}` | `Product`, `Inventory`, `FulfillmentOrder` |
| | Value Object | `{Concept}` | `Money`, `ProductStatus`, `FulfillmentStatus` |
| | Domain Event | `{Entity}Event` (sealed class) | `InventoryEvent.StockReserved` |
| | Domain Exception | `{Concept}Exception` | `InsufficientStockException` |
| **Application** | UseCase (Inbound Port) | `{Action}{Entity}UseCase` | `CreateProductUseCase`, `ReserveStockUseCase` |
| | Service (UseCase 구현) | `{Entity}Service` | `ProductService`, `InventoryService` |
| | Transactional Service | `{Entity}TransactionalService` | `OrderTransactionalService` |
| | Outbound Port | `{Purpose}Port` | `ProductRepositoryPort`, `OutboxPort`, `PaymentPort` |
| | Command/Result | UseCase 내부 data class | `CreateProductUseCase.Command`, `.Result` |
| **Infrastructure** | JPA Entity | `{Entity}JpaEntity` | `ProductJpaEntity`, `OutboxJpaEntity` |
| | ES Document | `{Entity}EsDocument` | `ProductEsDocument` |
| | JPA Repository | `{Entity}JpaRepository` | `ProductJpaRepository` |
| | QueryDSL Repository | `{Entity}QueryRepository` | `ProductQueryRepository` |
| | Port 구현체 (Adapter) | `{Purpose}Adapter` | `ProductRepositoryAdapter`, `PaymentAdapter` |
| | Kafka Consumer | `{Entity}EventConsumer` | `InventoryEventConsumer` |
| | Kafka Event DTO | `{Entity}Events` / `{Domain}KafkaEvents` | `OrderEvents`, `InventoryKafkaEvents` |
| | Outbox Publisher | `OutboxPollingPublisher` | 서비스별 동일 이름 |
| | Config | `{Purpose}Config` | `KafkaConfig`, `DataSourceConfig` |
| **Presentation** | Controller | `{Entity}Controller` | `ProductController` |
| | Exception Handler | `{Entity}ExceptionHandler` | `ProductExceptionHandler` |
| | Request DTO | `{Action}{Entity}Request` | `CreateProductRequest` |
| | Response DTO | `{Entity}Response` | `ProductResponse` |
원본 본문은 git history 참조 (commit before this PR — `feat/adr-cleanup-conventions-standards` 머지 직전).

### 2. DI(의존성 주입) 방향 규칙
## Related

```
Controller → UseCase (interface)
Service (impl) → Port (interface)
Adapter (impl)
```

- **Controller**는 UseCase 인터페이스에만 의존 (구현체 모름)
- **Service**는 Outbound Port 인터페이스에만 의존 (JPA/Kafka 모름)
- **Adapter**는 Port를 구현하고, 프레임워크 기술에 의존
- 생성자 주입만 사용 (field injection 금지)
- `@Component`/`@Service`로 Spring 자동 주입

### 3. Domain 모델 생성 패턴

```kotlin
class Product private constructor(
val id: Long?,
val name: String,
// ...
) {
companion object {
fun create(name: String, ...): Product { ... } // 신규 생성
fun restore(id: Long, ...): Product { ... } // DB 복원
}

// 비즈니스 메서드
fun updateName(name: String) { ... }
}
```

- `private constructor` + factory method (`create`, `restore`)
- `create`: 비즈니스 검증 포함, id는 null
- `restore`: DB에서 복원, 검증 없이 상태 재구성
- mutable 필드는 `private set` + getter 메서드 또는 Kotlin property

### 4. JPA Entity ↔ Domain 매핑

```kotlin
@Entity @Table(name = "products")
class ProductJpaEntity(
@Id @GeneratedValue val id: Long = 0,
val name: String,
// ...
) {
fun toDomain(): Product = Product.restore(id, name, ...)

companion object {
fun fromDomain(product: Product) = ProductJpaEntity(
id = product.id ?: 0,
name = product.name,
// ...
)
}
}
```

- `toDomain()`: JPA Entity → Domain Model (인스턴스 메서드)
- `fromDomain()`: Domain Model → JPA Entity (companion object)

### 5. UseCase 인터페이스 패턴

```kotlin
interface CreateProductUseCase {
fun execute(command: Command): Result

data class Command(val name: String, val price: BigDecimal)
data class Result(val id: Long, val name: String, val price: BigDecimal)
}
```

- 단일 `execute` 메서드
- `Command`/`Query`/`Result`는 UseCase 내부 data class로 정의
- 조회 UseCase는 `Query` 사용

### 6. Transactional Service 분리 패턴

외부 API 호출이 포함된 유스케이스에서 DB 커넥션 점유를 최소화하기 위해 사용:

```
TX1 (짧은 트랜잭션): 엔티티 PENDING 저장
→ 외부 API 호출 (트랜잭션 밖)
→ TX2 (짧은 트랜잭션): 결과 반영 (COMPLETED/FAILED)
```

- `{Entity}TransactionalService`: 짧은 DB 트랜잭션만 담당
- `{Entity}Service`: 전체 흐름 오케스트레이션

### 7. 테스트 파일 규칙

- 파일명: `{ClassName}Test.kt`
- 프레임워크: Kotest BehaviorSpec + MockK
- Domain 테스트: Mock 없이 순수 단위 테스트
- Application 테스트: Outbound Port를 MockK로 대체
- 위치: `src/test/kotlin/{동일 패키지}/`

### 8. Application Main Class

```kotlin
@SpringBootApplication
class {Service}Application

fun main(args: Array<String>) {
runApplication<{Service}Application>(*args)
}
```

- 파일명: `{Service}Application.kt`
- 위치: `com.kgd.{service}` 루트 패키지

## Alternatives Considered

1. **별도 conventions 문서로만 관리**: ADR로 결정 기록을 남기지 않으면 "왜 이 컨벤션인지" 추적 불가.
2. **코드 생성 도구(Archetype) 도입**: 현 규모에서는 과도. 문서 레퍼런스가 더 유연.

## Consequences

**긍정적:**
- 새 서비스/모듈 추가 시 일관된 구조 보장
- AI 에이전트가 코드 생성 시 참조할 단일 레퍼런스
- 기존 분산된 문서의 빈 곳(네이밍, DI, 도메인 패턴)을 보완

**부정적:**
- 컨벤션 변경 시 이 ADR도 함께 업데이트 필요
- 기존 코드 중 컨벤션에 맞지 않는 부분은 점진적 정리 필요

## References

- 패키지 구조 상세: `docs/conventions/package-structure.md`
- Clean Architecture 원칙: `docs/architecture/00.clean-architecture.md`
- 테스트 규칙: `docs/standards/test-rules.md`
- Kafka 토픽 컨벤션: `docs/architecture/kafka-convention.md`
- API 응답 포맷: `docs/conventions/api-format.md`
- 거버넌스: [ADR-0026 docs taxonomy](ADR-0026-docs-taxonomy.md)
78 changes: 19 additions & 59 deletions docs/adr/ADR-0016-service-local-docs.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,21 @@
# ADR-0016 서비스별 문서 분산 배치
# ADR-0016 [Moved] 서비스별 문서 분산 배치

## Status
Accepted

## Context

현재 모든 서비스 문서가 루트 `docs/` 디렉토리에 중앙 집중되어 있다:
- `docs/services/{service}.md` — 서비스별 설명서
- `docs/adr/ADR-001~004` — charting 전용 ADR이 플랫폼 ADR과 혼재

문제점:
1. 에이전트가 특정 서비스 작업 시 해당 서비스 문서를 자동으로 참조하지 못함 (경로에 없으므로)
2. charting 전용 ADR이 플랫폼 ADR과 섞여 있어 분류가 모호함
3. 서비스 삭제/분리 시 관련 문서를 별도로 찾아 정리해야 함
4. Claude Code는 작업 경로의 CLAUDE.md를 자동 로드하므로, 서비스별 컨텍스트 파일이 있으면 자동 참조 가능

OpenAI Harness Engineering의 "Strategic Context Management" 원칙 참고:
계층적 문서 구조(루트=공통, 하위=특화)로 토큰 효율성과 컨텍스트 정확성을 높일 수 있다.

## Decision

### 분류 기준
- **루트 `docs/`**: 2개 이상 서비스에 공통으로 적용되는 문서
- **`{service}/docs/`**: 해당 서비스에만 적용되는 문서

### 이동 대상
| 기존 위치 | 이동 위치 |
|-----------|-----------|
| `docs/services/{service}.md` | `{service}/docs/service.md` |
| `docs/adr/ADR-001~004` (charting 전용) | `charting/docs/adr/` |

### 유지 대상 (루트 docs/)
| 디렉토리 | 사유 |
|-----------|------|
| `docs/architecture/` | 플랫폼 공통 아키텍처 |
| `docs/adr/ADR-0001~0015` | 플랫폼 레벨 결정 |
| `docs/conventions/` | 전 서비스 공통 컨벤션 |
| `docs/standards/` | 전 서비스 공통 표준 |
| `docs/specs/` | 피처 스펙 (크로스 서비스 가능) |
| `docs/plans/` | 구현 계획 |
| `docs/runbooks/` | 운영 가이드 |
| `docs/benchmarks/` | 벤치마크 리포트 |

### 서비스별 CLAUDE.md
각 서비스 루트에 CLAUDE.md를 생성하여:
- 서비스 개요 및 로컬 docs 맵
- 서비스 특화 규칙/주의사항
- 빌드 명령어

## Alternatives Considered

1. **현상 유지 (중앙 집중)**: 관리 포인트는 적지만 에이전트 자동 참조 불가
2. **AGENTS.md 별도 사용**: OpenAI Codex용 컨벤션이므로 Claude Code에서는 CLAUDE.md로 통일이 적절

## Consequences

- 에이전트가 서비스 작업 시 해당 서비스의 CLAUDE.md + docs/를 자동 참조
- 서비스 독립성 강화 (삭제/분리 시 문서도 함께 이동)
- `docs/services/` 디렉토리 제거 (역할을 서비스별 docs/로 이관)
- 루트 CLAUDE.md의 Navigation에 서비스별 문서 안내 추가 필요

Moved (재분류) — 2026-04-26

## 새 위치

`docs/standards/service-local-docs.md`

## 이동 사유

문서 조직 정책 (계층적 문서 배치 + CLAUDE.md 자동 로드) 으로, ADR-0026 분류 기준상 **architecturally significant decision 이 아닌 standards** (도구/프로세스 정책) 로 판정.

## History

원본 본문은 git history 참조 (commit before this PR — `feat/adr-cleanup-conventions-standards` 머지 직전).

## Related

- 거버넌스: [ADR-0026 docs taxonomy](ADR-0026-docs-taxonomy.md)
Loading
Loading