8.4 KiB
title, source_type, url, archive_url, related_branches, related_projects, tags, created, last_reviewed
| title | source_type | url | archive_url | related_branches | related_projects | tags | created | last_reviewed | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| company-tech-blog / Explicit Architecture — DDD, Hexagonal, Onion, Clean, CQRS 통합 (Herberto Graça) | company-tech-blog | https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/ |
|
|
|
2026-06-04 | 2026-06-04 |
Explicit Architecture — DDD, Hexagonal, Onion, Clean, CQRS 통합 (Herberto Graça)
Layer:
raw/company-tech-blogs/— Herberto Graça 의 "DDD, Hexagonal, Onion, Clean, CQRS, … How I put it all together" (2017-11-16) 발췌. hexagonal 아키텍처에서 CQRS query handler 가 Application Service (Use Case) 를 어떻게 다루는지의 대표적 설명.출처 신뢰도:
engineering-blog등급 — 저자의 개인 기술 블로그. 공식 표준 아님. 그러나 DDD/hexagonal/CQRS 통합 설명에서 커뮤니티에서 자주 인용되는 article.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-application-query-bypass-contract | D2 (use-case layer ceremony 의 bypass — CQRS query handler 가 Application Service 를 거치지 않고 직접 optimized query 를 실행하는 패턴) 의 architectural reference. query side 가 "optimized query that will simply return some raw data" 로 작동하는 설계 근거 |
출처 / Source
- 원본 URL: https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/
- 아카이브 URL:
- 저자 / 조직: Herberto Graça — 개인 기술 블로그 (hgraca.com)
- 발행일: 2017-11-16
- 마지막 확인일: 2026-06-04
왜 저장했는지 / Why archived
ca-tmpl 의 alternative 3 (CQRS query handler pattern) 의 architectural reference. Graça 는 hexagonal + CQRS 통합 설명에서 query handler 가 Application Service 와 다른 역할을 한다는 것을 명시적으로 설명. 특히 "The Query object will contain an optimized query that will simply return some raw data" 는 query side 가 domain aggregate 로딩 없이 직접 DTO 반환이 가능함을 시사.
핵심 인용 / Key quotes (verbatim)
[§CQRS query side — query object] "The Query object will contain an optimized query that will simply return some raw data to be shown to the user."
[§Application Services — role definition] "Application Services (also known as workflow services, use cases, or interactors) are used to orchestrate the steps required to fulfill the commands imposed by the client."
[§Application Services — typical steps] "1. use a repository to find one or several entities; 2. tell those entities to do some domain logic; 3. and use the repository to persist the entities again."
[§Command/Query Bus without separate bus] "Controllers can depend on Query objects [directly], distinct from Application Services."
[§DTO for view] "That data will be returned in a DTO which will be injected into a ViewModel."
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| HGRACA-CQRS-C1 | CQRS query side 에서 Query object 는 optimized query 를 담고 user 에게 보여줄 raw data 를 반환하도록 설계됨 — 도메인 aggregate 조작 없이 단순 데이터 반환 | [§CQRS query side] "The Query object will contain an optimized query that will simply return some raw data to be shown to the user." | engineering-blog |
CQRS query side 설계 — query handler 가 Application Service 를 거치지 않는 패턴 | "모든 읽기가 Use Case Application Service 를 거칠 필요 없다" 는 공식 표준이 아님 — engineering-blog 등급의 저자 설계 의견 |
| HGRACA-CQRS-C2 | Application Service (Use Case, Interactor) 의 역할은 command 를 오케스트레이션 — entity 를 repository 로 find, domain logic 실행, repository 로 persist 하는 3단계 | [§Application Services] "Application Services...are used to orchestrate the steps required to fulfill the commands imposed by the client." + "1. use a repository to find one or several entities; 2. tell those entities to do some domain logic; 3. and use the repository to persist the entities again." | engineering-blog |
command side (write path) 의 Application Service 역할 정의 | query side 에도 Application Service 가 필요하다는 주장의 근거는 아님 — 이 3단계는 command 를 대상으로 명시 |
| HGRACA-CQRS-C3 | query side 에서 반환되는 데이터는 DTO 형태로 ViewModel 에 주입됨 | [§DTO for view] "That data will be returned in a DTO which will be injected into a ViewModel." | engineering-blog |
CQRS query side 반환 타입 — application layer 가 JPA entity 를 직접 반환하지 않음 | DTO 가 반드시 별도 record/class 여야 한다는 강제는 아님 — interface projection 도 DTO 패턴의 변형으로 간주 가능 |
| HGRACA-CQRS-C4 | Query Bus 없는 구조에서 Controller 가 Query object 에 직접 의존 하는 패턴이 제시됨 — Application Service 를 거치지 않는 thin read path 의 구조적 근거 | [§Without Command/Query Bus] "Controllers can depend on Query objects [directly], distinct from Application Services." | engineering-blog |
Command/Query Bus 를 별도 도입하지 않는 단순 CQRS 구현 | Controller 가 Query object 에 직접 의존해도 hexagonal 의 transport 타입이 application layer 에 leak 해선 안 된다 는 제약은 본 인용이 직접 다루지 않음 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
HGRACA-CQRS-C1: query side 가 "optimized query + raw data return" 으로 작동할 수 있다는 설계 제안HGRACA-CQRS-C2: Application Service 의 3단계 오케스트레이션은 command path 에 명시적으로 귀속HGRACA-CQRS-C3: query side 반환 타입은 DTO (domain entity 가 아님)HGRACA-CQRS-C4: Controller → Query object 직접 의존 패턴 (bus 없는 CQRS)
- 이 자료가 증명하지 않는 것:
- hexagonal 아키텍처에서 "thin read path" 에도 transport type (HTTP, gRPC) 이 application layer 에 leak 하지 않아야 한다는 설계 제약 — Graça 의 diagram 은 이 경계를 명시하지만 본 발췌 인용에는 포함되지 않음
- Query object 또는 query handler 를 ArchUnit 으로 정적 강제하는 방법
- Spring Boot 환경에서 query handler 를 어느 Gradle module 에 배치하는지
- transaction 없는 thin read path 의 Hibernate session 동작
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-tmpl 의 thin read path 에서
@Controller(org.springframework.web) 타입이 application port 에 노출되지 않도록 query service / read port 를 어느 layer 에 배치할지 결정 (D1 의 핵심) - ca-tmpl 의 ArchUnit rule 이 Controller → QueryService 직접 의존을 허용할지, 또는 QueryUseCase (인터페이스) 를 항상 중간에 두도록 강제할지
- ca-tmpl 의 thin read path 에서
메모 / Notes
- Graça 의 글은 2017년 작성이지만 hexagonal + CQRS 통합에서 가장 자주 인용되는 레퍼런스 중 하나. 한국어 번역본도 존재.
- HGRACA-CQRS-C1 의 핵심 의미: query 는 domain 오케스트레이션 없이 read-optimized path 로 처리 가능 → Application Service (Use Case) 를 무조건 통과할 필요가 없음을 지지. 단 engineering-blog 등급이므로 official-vendor-doc 이나 official-standard 대비 낮은 신뢰도.
- HGRACA-CQRS-C4 에서 "Controller 가 Query object 에 직접 의존" 한다는 설명은 ca-tmpl 의 hexagonal rule (web adapter 가 application layer 를 거쳐야 함) 과 충돌처럼 보이나, Query object 가 application layer 에 위치하면 interface dependency 는 여전히 inward pointing — hexagonal violation 아님
Related / 관련
- raw/official-docs/cqrs-fowler-bliki — CQRS 정의 상위 문서
- raw/company-tech-blogs/domain-event-sourcing-vs-cqrs-greg-young — CQRS 원작자 Greg Young 의 정의
- raw/official-docs/spring-data-jpa-projections-spring-official — projection (DTO) 의 Spring 공식 mechanism
- raw/branch-notes/feature-application-port-usecase-contract — QueryUseCase 선행 계약