๐ท ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ(Hexagonal Architecture)๋?
- ๋ชฉ์ : ๋น์ฆ๋์ค ๋ก์ง(๋๋ฉ์ธ, ์ ์ค์ผ์ด์ค)์ ์ธ๋ถ ๊ธฐ์ (DB, UI, ๋ฉ์์ง ํ, API ๋ฑ)๋ก๋ถํฐ ๋ถ๋ฆฌํด์ ํต์ฌ ๋ก์ง์ ์์ ์ ์ผ๋ก ๋ณดํธํ๊ณ , ๊ธฐ์ ์์๋ ์ฝ๊ฒ ๊ต์ฒดํ ์ ์๋๋ก ํ๋ ์ํคํ ์ฒ ํจํด
- ๋ค๋ฅธ ์ด๋ฆ: Ports and Adapters ํจํด
๐งฉ ํต์ฌ ๊ฐ๋

1. ์ ํ๋ฆฌ์ผ์ด์ ์ฝ์ด (Application Core)
-
- ๋๋ฉ์ธ ๋ชจ๋ธ(์ํฐํฐ, ๊ฐ ๊ฐ์ฒด ๋ฑ)
- ์ ์ค์ผ์ด์ค(์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค)
- ์ธ๋ถ ๊ธฐ์ ์ ์ ํ ์์กดํ์ง ์๋ ์์ํ ๋ก์ง
- ํฌํธ (Ports)
- ์ฝ์ด์ ์ธ๋ถ ์ธ๊ณ๋ฅผ ์ฐ๊ฒฐํ๋ ์ถ์ ์ธํฐํ์ด์ค
- ๋ ๊ฐ์ง๋ก ๋๋จ
- ์ธ์ปค๋ฐ ํฌํธ (Incoming Port)
→ ์ธ๋ถ์์ ์ฝ์ด๋ฅผ ํธ์ถํ ๋ ์ฌ์ฉ (์: REST Controller๊ฐ ํธ์ถํ๋ UseCase ์ธํฐํ์ด์ค) - ์์๊ณ ์ ํฌํธ (Outgoing Port)
→ ์ฝ์ด์์ ์ธ๋ถ๋ก ๋๊ฐ ๋ ์ฌ์ฉ (์: Repository ์ธํฐํ์ด์ค, ์ธ๋ถ API ํธ์ถ ์ธํฐํ์ด์ค)
- ์ธ์ปค๋ฐ ํฌํธ (Incoming Port)
- ์ด๋ํฐ (Adapters)
- ํฌํธ ์ธํฐํ์ด์ค๋ฅผ ์ค์ ๊ตฌํํ๋ ๊ธฐ์ ์ ์์
- ๋ ๊ฐ์ง๋ก ๋๋จ
- ๋๋ผ์ด๋น ์ด๋ํฐ (Driving Adapter)
→ ์ธ์ปค๋ฐ ํฌํธ๋ฅผ ๊ตฌํํ๋ ์ธ๋ถ ๊ธฐ์ (์: Controller, CLI, Event Listener) - ๋๋ฆฌ๋ธ ์ด๋ํฐ (Driven Adapter)
→ ์์๊ณ ์ ํฌํธ๋ฅผ ๊ตฌํํ๋ ์ธ๋ถ ๊ธฐ์ (์: DB Repository, ๋ฉ์์ง ๋ธ๋ก์ปค, ์ธ๋ถ API ํด๋ผ์ด์ธํธ)
- ๋๋ผ์ด๋น ์ด๋ํฐ (Driving Adapter)
โ๏ธ ๋์ ํ๋ฆ ์์

- ์ฌ์ฉ์๊ฐ **Controller(๋๋ผ์ด๋น ์ด๋ํฐ)**๋ฅผ ํตํด ์์ฒญ →
- Controller๋ ์ธ์ปค๋ฐ ํฌํธ(UseCase ์ธํฐํ์ด์ค) ํธ์ถ →
- ์ ํ๋ฆฌ์ผ์ด์ ์ฝ์ด๊ฐ ๋น์ฆ๋์ค ๋ก์ง ์ํ →
- ํ์ํ๋ค๋ฉด ์์๊ณ ์ ํฌํธ(Repository ์ธํฐํ์ด์ค) ํธ์ถ →
- **๋๋ฆฌ๋ธ ์ด๋ํฐ(DB, ์ธ๋ถ API ๊ตฌํ์ฒด)**๊ฐ ์๋ต →
- ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ฐํ
๐ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ ์์ ๊ตฌ์กฐ (Java)
๐ฆ com.example.project
โฃ ๐ application // ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค (์ ์ค์ผ์ด์ค, ์ธ์ปค๋ฐ ํฌํธ)
โ โฃ ๐ port
โ โ โฃ ๐ in
โ โ โ โ ๐ CreateOrderUseCase.java
โ โ โ ๐ out
โ โ โ ๐ OrderRepository.java
โ โ ๐ service
โ โ ๐ CreateOrderService.java
โ
โฃ ๐ domain // ๋๋ฉ์ธ ๋ชจ๋ธ (์์ ๋น์ฆ๋์ค ๋ก์ง)
โ โฃ ๐ model
โ โ โฃ ๐ Order.java
โ โ โ ๐ Product.java
โ โ ๐ logic
โ โ ๐ OrderValidator.java
โ
โฃ ๐ adapter // ์ด๋ํฐ (ํฌํธ์ ์ค์ ๊ตฌํ)
โ โฃ ๐ in
โ โ โ ๐ web
โ โ โ ๐ OrderController.java
โ โ ๐ out
โ โ ๐ persistence
โ โฃ ๐ jpa
โ โ โฃ ๐ OrderJpaEntity.java
โ โ โฃ ๐ SpringDataOrderRepository.java
โ โ โ ๐ JpaOrderRepositoryAdapter.java
โ โ ๐ external
โ โ ๐ PaymentApiAdapter.java
โ
โฃ ๐ config // DI, ์ค์ ๊ด๋ จ
โ โ ๐ ApplicationConfig.java
โ
โ ๐ Application.java // ๋ฉ์ธ ์คํ ํ์ผ (Spring Boot ๋ฑ)
โฃ ๐ application // ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค (์ ์ค์ผ์ด์ค, ์ธ์ปค๋ฐ ํฌํธ)
โ โฃ ๐ port
โ โ โฃ ๐ in
โ โ โ โ ๐ CreateOrderUseCase.java
โ โ โ ๐ out
โ โ โ ๐ OrderRepository.java
โ โ ๐ service
โ โ ๐ CreateOrderService.java
โ
โฃ ๐ domain // ๋๋ฉ์ธ ๋ชจ๋ธ (์์ ๋น์ฆ๋์ค ๋ก์ง)
โ โฃ ๐ model
โ โ โฃ ๐ Order.java
โ โ โ ๐ Product.java
โ โ ๐ logic
โ โ ๐ OrderValidator.java
โ
โฃ ๐ adapter // ์ด๋ํฐ (ํฌํธ์ ์ค์ ๊ตฌํ)
โ โฃ ๐ in
โ โ โ ๐ web
โ โ โ ๐ OrderController.java
โ โ ๐ out
โ โ ๐ persistence
โ โฃ ๐ jpa
โ โ โฃ ๐ OrderJpaEntity.java
โ โ โฃ ๐ SpringDataOrderRepository.java
โ โ โ ๐ JpaOrderRepositoryAdapter.java
โ โ ๐ external
โ โ ๐ PaymentApiAdapter.java
โ
โฃ ๐ config // DI, ์ค์ ๊ด๋ จ
โ โ ๐ ApplicationConfig.java
โ
โ ๐ Application.java // ๋ฉ์ธ ์คํ ํ์ผ (Spring Boot ๋ฑ)
๐งฉ ๊ตฌ์กฐ ์ค๋ช
- application
- ํฌํธ(์ธํฐํ์ด์ค)์ ์๋น์ค(์ ์ค์ผ์ด์ค) ์ ์
- ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ง์ ํธ์ถํ๋ ์ง์ ์
- domain
- ์์ ๋๋ฉ์ธ ๋ชจ๋ธ (Entity, Value Object, ๋๋ฉ์ธ ๋ก์ง)
- ์ธ๋ถ ๊ธฐ์ ๊ณผ ๋ฌด๊ด → ํ ์คํธ์ ์ ์ง๋ณด์ ์ฉ์ด
- adapter
- in → ๋๋ผ์ด๋น ์ด๋ํฐ (Controller, CLI, Event Listener ๋ฑ)
- out → ๋๋ฆฌ๋ธ ์ด๋ํฐ (DB, ์ธ๋ถ API, ๋ฉ์์ง ๋ธ๋ก์ปค ๊ตฌํ์ฒด)
- config
- Spring DI ์ค์ , Bean ๋ฑ๋ก
๐ค DDD , ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ ๋ ๊ฐ๋ ์ ๊ด๊ณ
- ๐งฉ DDD (Domain-Driven Design) = “๋ฌด์์ ์ค์ฌ์ผ๋ก ๊ฐ๋ฐํ ๊น?” → ๋น์ฆ๋์ค ๋๋ฉ์ธ
- ์ ์: ๋น์ฆ๋์ค ๋๋ฉ์ธ์ ๋ณต์ก์ฑ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ฐ ๋ฐฉ๋ฒ๋ก
- ํต์ฌ ๋ชฉํ: ๊ธฐ์ ์ด ์๋๋ผ **๋๋ฉ์ธ ๋ก์ง(๋น์ฆ๋์ค ๊ท์น)**์ ์ค์ฌ์ ๋๊ณ ๊ฐ๋ฐ
- 3๊ณ์ธต ๊ตฌ์กฐ๋ก ๊ตฌํํ๋ ๊ฒ ์ผ๋ฐ์ :
- Application Layer
- ๋๋ฉ์ธ๊ณผ ์ ์ฅ์๋ฅผ ํ์ฉํด ์ ์ค์ผ์ด์ค ์คํ (์๋น์ค, API ์ ๊ณต)
- Domain Model Layer
- ์ํฐํฐ/๋ฐธ๋ฅ ๊ฐ์ฒด/์ ๊ทธ๋ฆฌ๊ฑฐํธ๋ฅผ ํตํด ๋น์ฆ๋์ค ๋ก์ง ์ํ
- Infrastructure Layer
- DB, ๋ฉ์์ง ํ, ์ธ๋ถ API ๋ฑ ์ธ๋ถ์์ ์ฐ๊ฒฐ ๋ด๋น
- Application Layer
- ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ (Hexagonal Architecture, Ports & Adapters) = “๊ทธ ๋๋ฉ์ธ์ ์ด๋ป๊ฒ ์ง์ผ์ค๊น?” → ์ํคํ ์ฒ์ ๊ตฌ์กฐ
- ์ ์: ํฌํธ(์ธํฐํ์ด์ค)์ ์ด๋ํฐ(๊ตฌํ์ฒด) ๊ฐ๋
์ ํ์ฉํด
๋๋ฉ์ธ ๋ก์ง์ ์ธ๋ถ ๊ธฐ์ (DB, UI, ํ๋ ์์ํฌ)๋ก๋ถํฐ ๊ฒฉ๋ฆฌํ๋ ์ํคํ ์ฒ ํจํด - ํต์ฌ ๋ชฉํ:
- ๋๋ฉ์ธ ๋ก์ง์ด ์ธ๋ถ ๊ธฐ์ ์ ์ํฅ์ ๋ฐ์ง ์๋๋ก ๋ณดํธ
- ๊ธฐ์ ์์๋ ์ฝ๊ฒ ๊ต์ฒด ๊ฐ๋ฅ (DB → Redis, REST → gRPC ๋ฑ)

- ์ ๋ฆฌ
- DDD๋ ๋น์ฆ๋์ค๋ฅผ ์ฝ๋๋ก ์ฎ๊ธฐ๋ ๋ฐฉ๋ฒ๋ก
→ ๋๋ฉ์ธ ์ค์ฌ ์ค๊ณ - ํฅ์ฌ๊ณ ๋ ์ ๊ทธ ์ค๊ณ๋ฅผ ๊ธฐ์ ๋ก๋ถํฐ ์ง์ผ์ฃผ๋ ์ํคํ
์ฒ
→ ํฌํธ์ ์ด๋ํฐ๋ก ๊ฒฐํฉ๋ ์ต์ํ - ๋ ๊ฐ๋
์ ์๋ก ๋ณด์์
- DDD๋ก ๋ชจ๋ธ๋ง → ํฅ์ฌ๊ณ ๋ ๋ก ๊ตฌ์กฐํ → ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ ํฅ์
- DDD๋ ๋น์ฆ๋์ค๋ฅผ ์ฝ๋๋ก ์ฎ๊ธฐ๋ ๋ฐฉ๋ฒ๋ก
๐ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ(Hexagonal, Ports & Adapters)์ ํด๋ฆฐ ์ํคํ ์ฒ(Clean Architecture)
๊ตฌ๋ถ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ ํด๋ฆฐ ์ํคํ ์ฒ
| ์ ์์ | Alistair Cockburn | Robert C. Martin |
| ๊ตฌ์กฐ | ์ฝ์ด + ํฌํธ + ์ด๋ํฐ | ๋์ฌ์ ๊ณ์ธต ๊ตฌ์กฐ |
| ํต์ฌ ๊ฐ๋ | ํฌํธ์ ์ด๋ํฐ | ์ํฐํฐ, ์ ์ค์ผ์ด์ค, ์ธํฐํ์ด์ค ์ด๋ํฐ |
| ๋ชฉํ | ๊ธฐ์ ๋ ๋ฆฝ์ฑ, ์ ์ฐํ ํ์ฅ | ์ฑ ์ ๋ถ๋ฆฌ, ์์กด์ฑ ๊ท์น ๊ฐํ |
| ๋ณต์ก๋ | ์๋์ ์ผ๋ก ๋จ์ | ์๋์ ์ผ๋ก ์ธ๋ฐํ๊ณ ๋ณต์ก |
| ์ ์ฉ ์์ | DB ๊ต์ฒด, API/๋ฉ์์ง ๊ต์ฒด | ๋๊ท๋ชจ ์์คํ , ๊ณ์ธต ๋ถ๋ฆฌ ์ฒ ์ ํ ํ์ํ ๋ |
- ํฅ์ฌ๊ณ ๋ ์ ๋น๊ต์ ๋จ์ํด์ ๊ธฐ์ ๋ ๋ฆฝ์ฑ์ ํ๋ณดํ๋ ๋ฐ ๊ฐ์
- ํด๋ฆฐ ์ํคํ ์ฒ๋ ๊ณ์ธต์ ์ธ๋ฐํ ๋๋ ๋ณต์กํ ์์คํ ์์ ์ ์ง๋ณด์์ ๊ฐ์
- ๋ ๋ค “๋๋ฉ์ธ ๋ก์ง์ ๋ณดํธํ๋ค”๋ ๊ณตํต ๋ชฉ์ ์ ๊ฐ๊ณ ์์
- ์ค์ ํ์ฅ์์๋ ํฅ์ฌ๊ณ ๋ ์ ๋จผ์ ์ ์ฉํ๊ณ , ์์คํ
์ด ์ปค์ง๋ฉด ํด๋ฆฐ ์ํคํ
์ฒ๋ก ํ์ฅํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์

'BACKEND' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Architectural Pattern] CQRS (Command Query Responsibility Segregation) (0) | 2025.08.29 |
|---|---|
| [java]๋ฆฌํ๋ ์ (reflection) (0) | 2025.08.22 |
| [java] Spring AOP(Aspect-Oriented Programming) (0) | 2025.08.22 |
| [java]ThreadLocal ์ฌ์ฉ๋ฒ (0) | 2025.08.21 |
| [Architecture]๋ฉํฐํ ๋์(Multi-tenancy) -Shared Schema ๋ฐฉ์ (0) | 2025.08.21 |