9.5 KiB
9.5 KiB
title, source_type, status, confidence, derived_from, related_projects, audience, purpose, last_reviewed, status_label
| title | source_type | status | confidence | derived_from | related_projects | audience | purpose | last_reviewed | status_label | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| report | draft | unknown |
|
|
self | big-picture-understanding | draft |
{{title}}
이 문서는 이해를 위한 derived report입니다.
SSOT는raw/branch-notes/와wiki/projects/의 canonical 문서입니다.
이 문서는 ca-tmpl 전체 구조를 사람이 읽고 설명할 수 있도록 재구성합니다.
0. Reading Guide
이 문서는 무엇을 설명하는가
<ca-tmpl 전체 구조, 목표, 핵심 계약, 구현 상태를 설명한다.>
먼저 읽어야 할 사람
<ca-tmpl의 큰 그림이 아직 안 잡힌 사람><branch-note를 읽기 전에 전체 지도가 필요한 사람><Clean Architecture skeleton의 운영 계약이 왜 필요한지 이해하려는 사람>
이 문서를 읽고 답할 수 있어야 하는 질문
- ca-tmpl은 무엇인가?
- 왜 도메인 기능을 제거했는가?
- 왜 운영 계약이 skeleton의 중심인가?
- 왜 branch-note가 많은가?
- 각 branch-note는 전체 skeleton의 어느 영역을 책임지는가?
- 현재 구현된 것과 아직 문서만 있는 것은 무엇인가?
SSOT
- Canonical:
wiki/projects/<canonical-project-doc>
- Raw / branch notes:
raw/branch-notes/<optional-branch-note>
이 문서의 한계
- 이 문서는 SSOT가 아니다.
- 구현 상태는 작성일 기준이다.
- 세부 결정은 각 branch-note와 canonical 문서를 확인해야 한다.
1. 이 프로젝트는 무엇인가
한 문장 정의
ca-tmpl은
<새 백엔드 프로젝트를 시작할 때 반복적으로 필요한 운영 계약>을 Clean Architecture 구조로 미리 고정해두는 skeleton이다.
하지 않는 것
- 특정 비즈니스 도메인을 제공하지 않는다.
- 특정 adapter를 무겁게 기본 탑재하지 않는다.
- raw branch-note에서 곧바로 blog/interview/portfolio로 파생하지 않는다.
- 운영 실패, 로그, trace, API envelope, module boundary를 프로젝트마다 임의로 재결정하지 않는다.
제공하는 것
- module/package boundary
- structured API response
- operational error category
- exception ownership
- boundary validation / mapper contract
- structured logging / tracing
- env-driven runtime configuration
- repository capability contract
- adapter failure mapping
- architecture test / contract test
- sample domain fixture
왜 skeleton인가
<도메인 기능 자체보다, 도메인을 얹었을 때 동일한 운영 계약과 아키텍처 경계를 유지하는 구조가 목적이기 때문이다.>
2. 이 프로젝트가 해결하는 핵심 문제
문제 1. 프로젝트마다 실패 처리 방식이 달라지는 문제
- 어떤 프로젝트는 validation 실패를 400으로 반환한다.
- 어떤 프로젝트는 같은 실패를 500으로 반환한다.
- 어떤 프로젝트는 raw exception message를 client에게 노출한다.
- 결과적으로 운영, 디버깅, API contract가 흔들린다.
문제 2. Clean Architecture 경계가 문서에만 남고 코드에서 무너지는 문제
- controller가 JPA entity를 직접 반환한다.
- application layer가 Spring/JPA 구현체를 직접 import한다.
- domain이 framework annotation을 알게 된다.
- adapter끼리 직접 참조하면서 순환 결합이 생긴다.
문제 3. 관측성 정보가 일관되지 않은 문제
- requestId가 없는 로그가 남는다.
- traceId와 correlationId 의미가 branch마다 다르다.
- 장애 발생 시 어떤 요청에서 어떤 dependency 실패가 났는지 추적하기 어렵다.
문제 4. 테스트가 구현 세부만 검증하고 계약 위반을 잡지 못하는 문제
- unit test는 통과하지만 architecture boundary가 깨진다.
- API response schema drift가 생겨도 release 전에 감지하지 못한다.
- contract violation이 warning-only로 남는다.
3. 전체 구조 요약
| 영역 | 역할 | 왜 필요한가 |
|---|---|---|
| domain-core | 순수 domain model, value object, domain rule | framework와 adapter로부터 business invariant를 보호 |
| application-core | use case, command/query, port, policy validation | business flow와 외부 구현체 사이의 경계 유지 |
| adapter-web | HTTP DTO, controller, validation, response mapper | 외부 HTTP 요청을 application contract로 변환 |
| adapter-persistence | JPA/RDBMS 저장소 구현, entity, mapper | persistence 기술을 application port 뒤로 숨김 |
| adapter-outbound | HTTP client, messaging, cache, notification adapter | 외부 dependency 세부 구현을 격리 |
| shared-contract | envelope, error code, header/log/metric registry | skeleton-wide operational contract 공유 |
| app-bootstrap | Spring Boot entrypoint, DI wiring, runtime config | composition root로 runtime module을 조립 |
| sample-portfolio | skeleton contract 검증용 fixture | 실제 domain 없이 contract를 검증 |
4. 핵심 흐름
4.1 Request 처리 흐름
HTTP Request
→ adapter-web Request DTO
→ request validation
→ mapper
→ application Command/Query
→ use case
→ domain model / domain rule
→ output port
→ adapter-persistence or adapter-outbound
→ response mapper
→ structured envelope
4.2 Error 처리 흐름
Exception or failure
→ layer-specific exception ownership
→ operational error mapping
→ error.code / error.category / retryable
→ structured envelope
→ structured log
→ trace correlation
4.3 Domain Feature 추가 흐름
presentation request/response DTO
→ request mapper
→ application command/query
→ use case
→ input port / output port
→ domain model / value object / domain rule
→ persistence model / repository adapter
→ response mapper
→ contract test
→ architecture rule
5. 주요 계약 묶음
| 계약 영역 | 담당 branch | 설명 | 현재 상태 |
|---|---|---|---|
| error / observability | raw/branch-notes/<...> |
error category, envelope, log/trace 기반 | <status> |
| API contract | raw/branch-notes/<...> |
versioning, pagination, headers, idempotency | <status> |
| boundary validation / mapper | raw/branch-notes/<...> |
DTO → command/query → domain 변환 경계 | <status> |
| module/package blueprint | raw/branch-notes/<...> |
Gradle multi-module, package responsibility | <status> |
| transaction / concurrency | raw/branch-notes/<...> |
transaction boundary, lock, retry, idempotency | <status> |
| sample fixture | raw/branch-notes/<...> |
skeleton contract 검증용 sample domain | <status> |
| architecture enforcement | raw/branch-notes/<...> |
ArchUnit / Gradle dependency guardrail | <status> |
6. 현재 구현 상태
| 영역 | 상태 | 근거 | 남은 위험 |
|---|---|---|---|
<영역> |
<decision-only / documented-only / local-verified / pending / unknown> |
<문서/코드/테스트> |
<위험> |
상태 값 정의
| 상태 | 의미 |
|---|---|
| decision-only | 결정은 있으나 구현/검증은 아직 없음 |
| documented-only | 문서상 계약만 있음 |
| local-verified | 로컬 코드/테스트로 검증됨 |
| pending | 아직 착수 전 또는 잔여 작업 존재 |
| unknown | 근거 부족으로 판단 불가 |
7. 큰 그림에서 가장 중요한 설계 판단
판단 1. <판단 이름>
- 결정:
- 이유:
- 대안:
- 선택하지 않은 이유:
- 근거:
- 남은 리스크:
판단 2. <판단 이름>
- 결정:
- 이유:
- 대안:
- 선택하지 않은 이유:
- 근거:
- 남은 리스크:
8. 내가 설명할 수 있어야 하는 문장
30초 설명
<ca-tmpl을 30초 안에 설명하는 문장>
2분 설명
<면접/리뷰/동료 설명에서 말할 수 있는 설명>
깊게 질문받았을 때
Q. 왜 도메인 기능을 제거했나?
A. <답변>
Q. 왜 sample-portfolio가 필요한가?
A. <답변>
Q. 왜 shared-contract가 필요한가?
A. <답변>
Q. 왜 architecture test가 필요한가?
A. <답변>
9. 아직 이해가 부족한 부분
| 질문 | 왜 헷갈리는가 | 확인할 문서 | 확인할 코드 |
|---|---|---|---|
10. 다음에 읽을 문서
wiki/reports/ca-tmpl/01-module-boundary-reportwiki/reports/ca-tmpl/02-operational-error-observability-reportwiki/reports/ca-tmpl/03-api-contract-reportwiki/reports/ca-tmpl/04-boundary-validation-mapper-report