init: 클린 아키텍처 백엔드

This commit is contained in:
DongHyeonka
2026-07-24 14:29:36 +09:00
parent 9eed16d097
commit 821fe00c32
971 changed files with 74769 additions and 1 deletions
+60
View File
@@ -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
```