init: 클린 아키텍처 백엔드
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# adapter:inbound:graphql — inbound GraphQL adapter (skeleton machinery)
|
||||
|
||||
## Registered identity
|
||||
|
||||
- Module ID: `adapter-inbound-graphql`
|
||||
- Gradle path: `:adapter:inbound:graphql`
|
||||
- Focused test: `./gradlew :adapter:inbound:graphql:test --console=plain`
|
||||
- Runtime baseline: Java 21; repository framework baseline: Spring Boot 4.0.0.
|
||||
- Registry SSOT: `.harness/project/modules.yaml`.
|
||||
|
||||
Package root: `dev.caskeleton.adapter.inbound.graphql`.
|
||||
|
||||
코드 주석에서 덜어낸 **설계 결정의 근거**는 [README.md](README.md) 가 모아둔다 (이 문서는 모듈
|
||||
규칙 SSOT).
|
||||
|
||||
## Responsibility
|
||||
|
||||
- GraphQL 전송 인프라만: 최소 health 스키마(`skeleton.graphqls`) + `HealthGraphqlController`,
|
||||
프로토콜 에러 매핑(`GraphqlExceptionResolver`). Spring for GraphQL 이 스키마와 컨트롤러를
|
||||
자동 합성/바인딩하도록 얹는 얇은 계층이다.
|
||||
- feature-agnostic: `classpath:graphql/**` 스키마와 모든 `@Controller` `@QueryMapping`/
|
||||
`@MutationMapping` 을 generic 하게 합성한다. **WorkLog 등 구체 기능을 이름으로 알지 않는다.**
|
||||
|
||||
## Allowed
|
||||
|
||||
- `:application-core`, `:domain-core`, `:shared-contract`.
|
||||
- `spring-boot-starter-graphql`, `spring-boot-starter-web`, `jackson-datatype-jsr310`
|
||||
(전부 Spring Boot BOM 관리 — 버전 명시 없음).
|
||||
|
||||
## Forbidden
|
||||
|
||||
- outbound 어댑터(`:adapter:outbound:*`)에 대한 직접 의존 — 인바운드는 application 아웃바운드
|
||||
포트를 통해서만 persistence/messaging/cache/http 에 닿는다 (ArchUnit
|
||||
`INBOUND_ADAPTERS_DO_NOT_DEPEND_ON_OUTBOUND_ADAPTERS`, 일반 `..adapter.inbound..` 규칙이 이
|
||||
모듈을 자동 커버 — per-module 규칙 추가 불필요).
|
||||
- 프로덕션 feature 쿼리/뮤테이션을 스켈레톤에 두는 것 — health 표면만 (web 의
|
||||
`HealthcheckController` 와 동일 원칙). feature 스키마/컨트롤러/매퍼는 sample 모듈이 소유한다.
|
||||
- 모듈별 `yml` — 설정은 프레임워크 `spring.graphql.*` 로 composition-root `application.yml` 에 산다.
|
||||
|
||||
## Error mapping (`Category → ErrorType`)
|
||||
|
||||
feature 는 `ApiErrorCarrier` 를 구현한 예외(자신의 `ApiErrorCode` 를 실어)를 던지면
|
||||
`GraphqlExceptionResolver` 가 `GraphQLError`(ErrorType + `extensions{code, category}`)로 매핑한다.
|
||||
비-`ApiErrorCarrier` 예외는 `null` 반환 → 다른 resolver / Spring 기본 처리. 표는 [README.md](README.md).
|
||||
|
||||
## Feature 기여 방법
|
||||
|
||||
- **스키마**: `src/main/resources/graphql/*.graphqls` 를 두면 `classpath:graphql/**` 병합으로 합쳐진다.
|
||||
- **핸들러**: `@Controller` + `@QueryMapping`/`@MutationMapping` 빈을 등록하면 자동 바인딩된다.
|
||||
- **도메인 예외 매핑**: sample 이 자신의 `DataFetcherExceptionResolver` 를 추가해 도메인 예외를
|
||||
`PortfolioErrorCode` 로 매핑한다(스켈레톤 resolver 보다 앞 순서). 스켈레톤은 `ApiErrorCarrier` 만 처리.
|
||||
|
||||
`sample-portfolio` 를 지워도 스켈레톤은 health 스키마만으로 부팅한다 (disposability).
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
cd src
|
||||
./gradlew :adapter:inbound:graphql:test
|
||||
```
|
||||
Reference in New Issue
Block a user