1. Clean Architecture

cf. https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Clean Architecture๋ ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ฆ๋์ค ๋ก์ง๊ณผ์ธ๋ถ ์์คํ ์ ๋ถ๋ฆฌํ๋ ์ํคํ ์ฒ๋ค.- Hexagonal Architecture์์ ์๊ฐ ๋ฐ์ ํํ๋ก
- Robert Martin์ด๋ผ๋ ์ฌ๋์ด 2017๋ ์ ์ฑ ์ผ๋ก ์ถ๊ฐํ ๊ฐ๋ ์ด๋ค.
Hexagonal Architecture์ ๋งค์ฐ ์ ์ฌํ์ง๋ง ์ฉ์ด์ ๊ตฌ๋ถ์ด ์ฝ๊ฐ ๋ค๋ฅด๋ค
1.1 Clean Architecture Layers

Framework & Driver Layer- ์ธ๋ถ ๋ํ๋์๋ค์ด ์กด์ฌํ๋ ์์ญ์ด๋ค.
- ์๋ฅผ๋ค์ด Database, REST API Call, UI, ํ๋ ์์ํฌ ์ฝ๋๋ฑ์ด ๋ ์ ์๋ค.
Interface Adapters- Usecase์ Entities๋ฅผ ์ํด ์กด์ฌํ๋ ๋ ์ด์ด๋ค.
- ๊ฐ์ฅ ์ค์ํ ๋ก์ง์ด ์๋ฆฌ์ก๊ณ ์๋ Use Case์ Entities์์ ์ฌ์ฉํ๊ธฐ ๊ฐ์ฅ ํธํ ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๊ณ ์ ๋ฌํ๋ค.
Use Case- ์ ํ๋ฆฌ์ผ์ด์ ์ ํนํ๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์์ฑ๋๋ ์์น๋ค.
- ์์คํ ์ ๊ธฐ๋ฅ๋ค์ ๊ตฌํํ๊ณ ์ถํ ์๊ฐ๋ Entities๋ค์ด ์ ํ๋ฆฌ์ผ์ด์ ๋น์ฆ๋์ค ๋ก์ง์ ์ํ ํ ์ ์๋๋ก ์ ๋ํ๋ค.
Entities- ๊ธฐ์ ์ ๋ฐ์ ์ผ๋ก ์ ์ฉ๋๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์์ฑ๋๋ ์์น๋ค.
- ๊ธฐ์ ์ ๋จ ํ๋์ ์ ํ๋ฆฌ์ผ์ด์ ๋ง ์กด์ฌํ๋ค๋ฉด ๋๋ฉ์ธ ๊ฐ์ฒด๋ค ์ ๋๋ก ์๊ฐํด ๋ ๋๋ค.
1.2 Dependency Rule

- ์์ ๋ด๋ถ์ ์๋ ๋ ์ด์ด๋ ๋ฐ๊นฅ์ ๋ณ๊ฒฝ์ ์ํฅ์ ๋ฐ์ผ๋ฉด ์๋๋ค.
- ์ธ๋ถ ๋ ์ด์ด๋ ๋ด๋ถ ๋ ์ด์ด์ ์์กด ํ ์ ์๋ค. ํ์ง๋ง ๋ด๋ถ ๋ ์ด์ด๋ ์ธ๋ถ ๋ ์ด์ด์ ์์กดํ๋ฉด ์๋๋ค.
- ์์กด์ฑ์ ์ญ์ ์ ์ํด Dependency Inversion์ ์ฌ์ฉํ๋ค
1.3 Use Case

- Hexagonal Architecture์ ๊ฐ์ฅ ๋ค๋ฅธ์ (?) ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค.
- Clean Architecture๋ SRP (Single Responsibility Principle)์ ๊ฐ์กฐํ๋ค.
- ๋น์ฆ๋์ค ๋ก์ง ๋ ์ด์ด์์ ์คํํด์ผํ ๊ธฐ๋ฅ ํ๋ ํ๋๋ฅผ ํ ๋์ ํด๋์ค์ ์ ์ํ๋ค.
2. Hexagonal Architecture
2.1 Hexagonal Architecture๋?
Hexagonal Architecture๋ Domain์ ์ค์์ ๊ฐ์ธ๋ ์ํคํ ์ฒ์ค ๊ฐ์ฅ ๋จผ์ ๊ณ ์๋ ์ํคํ ์ฒ ์ค ํ๋์ด๋ค.Port and Adapter ํจํด์ผ๋ก๋ ๋ถ๋ฆฌ๋ฉฐ,- ๊ฐ์ธ์ ์ผ๋ก ์ด ๋ช ์นญ์ด ์กฐ๊ธ ๋ ์ํคํ ์ฒ์ ํน์ฑ์ ์ ํํํ๋ค๊ณ ์๊ฐํ๋ค.
- ๋์ด์
Layered Architecture์ฒ๋ผ Top Down ํํ๊ฐ ์๋๋ค. - ๋๋ฉ์ธ์ ์ค์ฌ์ผ๋ก ์ค๊ณ๋๊ณ ์ธ๋ถ ์์กด์ฑ๋ค์ Domain์ ์ค๊ณ์ ๋ง์ถฐ์ ํ๋ก๊ทธ๋๋ฐ ํ๊ฒ ๋๋ค.
- ๋๋ฉ์ธ์ด ์ค์ฌ์ ์๊ณ ๋ฐ๊นฅ์ด ๋ด๋ถ๋ก ์์กดํ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ๊ฒ ๋๋ค.
- ๊ฐ์ฅ ์ค์ฌ์๋ ๋๋ฉ์ธ์ด ์๊ธฐ ๋๋ฌธ์, ๋๋ฉ์ธ์ ๊ทธ ๋ฌด์์๋ ์์กดํ์ง ์๋ ๋ ๋ฆฝ์ ์ธ ์กด์ฌ๊ฐ ๋๋ค.
- ์ฆ, ์ค์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ธ๋ถ์ ์ํฅ์ ๋ฐ์ง ์๊ฒ ๋๋ค
2.2 Domain์ด๋?
Domain์ด๋ ์ํํธ์จ์ด์์ ํด๊ฒฐํ๊ณ ์ํ๋ ํน์ ๋น์ฆ๋์ค ์์ญ์ ์๊ธฐํ๋ค.Domain์ ์ค์ ๋น์ฆ๋์ค๋ ์์คํ ์ ๋ฌธ์ , ํ๋ก์ธ์ค, ๊ท์น ๋ฑ์ ํฌํจํ๋ฉฐ ์ด๋ฅผ ์ํํธ์จ์ด์ ๋ฐ์ํ๋ค.
์ํํธ์จ์ด์์ ํด๊ฒฐํด์ผํ๋ ํต์ฌ ๊ด์ฌ์ฌ๋ค.
ํต์ฌ ๊ด์ฌ์ฌ์ด๊ธฐ ๋๋ฌธ์ ํฐ ํ์์ ์์ฃผ ๋ฐ๋์ง ์๋๋ค.- ์ ์ ์๊ฑฐ๋ ์์คํ ์๋ ์ฃผ๋ฌธ, ๊ฒฐ์ , ์ฌ๊ณ ๊ด๋ฆฌ, ๊ณ ๊ฐ์ด ๋๋ฉ์ธ์ด ๋ ์ ์๋ค.
- (๋ง์น ์ฐ๋ฆฌ๊ฐ ์์ฑํ ๋ง์ดํฌ๋ก์๋น์ค์ฒ๋ผ)
- ์๋ฃ ์์คํ ์๋ ํ์ ๊ธฐ๋ก, ์์ฝ, ์น๋ฃ ๊ณผ์ ๋ฑ์ด ๋๋ฉ์ธ์ด ๋ ์ ์๋ค.
๋๋ฉ์ธ์ โ์ค์ โ ๋น์ฆ๋์ค์์ ํด๊ฒฐํด์ผํ๋ ๊ด์ฌ์ฌ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์๊ฐ ์๋ ์ฌ๋๋ค๊ณผ ์ฉ์ด ์ํต์ด ์ฉ์ดํ๋ค.
- ์ผ๋ฐ ์ฌ๋๋ค๋ ์ดํด ํ ์ ์๋ ์ฉ์ด์ธ โ์ฃผ๋ฌธโ, โ๊ฒฐ์ โ, โ์ฌ๊ณ โ๋ฑ์ด ์ฉ์ด๊ฐ ๋๊ธฐ ๋๋ฌธ์ ๋น๊ฐ๋ฐ์๋ ์ดํดํ๊ธฐ ์ฝ๋ค.
- ์ด๊ฑธ
Ubiquitous Language (๊ณตํต ์ธ์ด)๋ผ๊ณ ๋ถ๋ฅธ๋ค
2.3 Domain ๊ฐ์ฒด๋?
- Domain ๊ฐ์ฒด๋ Domain์ ์ถ์์ ์ผ๋ก ํํํ ํด๋์ค๋ค.
- ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ์ ์ํด์จ Entity๋ค์ด Domain ๊ฐ์ฒด์ ๋งค์ฐ โ๋น์ทโํ๋ค.
- Domain ๊ฐ์ฒด๋ ํ๋ก์ ํธ์์ ๊ฐ์ฅ ์ค์ฌ๋๋ ์ฝ๋์ด๋ค.
- ์๋ฅผ ๋ค์ด, ์ผํ๋ชฐ ์์คํ ์ ๊ฒฐ์ PG์ฌ๊ฐ A์ฌ์์ B๋ก ๋ณ๊ฒฝ๋๋ค๊ณ ํ๋๋ผ๋,
- ๋๋ฉ์ธ ๊ฐ์ฒด์ โ๊ฒฐ์ โ๋ผ๋ ๊ฐ๋ ์ด ์กด์ฌํด์ผํ๋ค๋ ๊ฑด ๋ณํ์ง ์๋๋ค.
- ๋๋ฉ์ธ์ ๋น์ฆ๋์ค ๋ก์ง์ ์ค์ํ ๋ถ๋ถ์ ๋ด๋นํ์ง๋ง, ์ธ๋ถ ์์กด์ฑ ์์ด ๊ฐ์ฅ ํ์ํ ๋ถ๋ถ๋ง ๋จ์ํ๊ฒ ๊ตฌํํ๋ค.
- ๋ค์ดํฐ๋ธ ์ธ์ด๋ก ๊ตฌํ ๊ฐ๋ฅํ ๋ก์ง๊ณผ ๊ฒ์ฆ์ ์ฃผ๋ก ๊ตฌํํ๋ค.
2.4 Domain ๊ฐ์ฒด ์์
1export class Order {2private readonly id : string;3private products: Product[];4private shippingAddress: Address;5private totalPrice: number;6private status: OrderStatus;78constructor(id: string, products: Product[], shippingAddress: Address) {9if (!id) throw new Error('Order ID๋ ํ์์ ๋๋ค.');10if (products.length === 0) throw new Error('์ฃผ๋ฌธ์ ์ฌํ ํ๋ ์ด์ ์์ด์ผ ํฉ๋๋ค.');11if (!shippingAddress) throw new Error('๋ฐฐ์ก์ง ์ ๋ณด๋ ํ์์ ๋๋ค.');1213this.id = id;14this.products = products;15this.shippingAddress = shippingAddress;16this.totalPrice = this.calculateTotalPrice();17this.status = OrderStatus.PENDING;18}1920// ์ฌ๊ธฐ๋ถํฐ Business Logic21addProduct(product: Product): void {22this.products.push(product);23this.totalPrice = this.calculateTotalPrice();24}25removeProduct(productId: string): void {}26changeShippingAddress(newAddress: Address): void {}27completeOrder(): void {}28cancelOrder(): void {}29calculateTotalPrice() : number {}30}
2.5 Domain Business Logic
1export class Order {2// ์๋ต3addProduct(product: Product): void {4this.products.push(product)5this.totalPrice = this.calculateTotalPrice()6}78removeProduct(productId: string): void {9this.products = this.products.filter((product) => product.id !== productId)10// ๊ฒ์ฆ11if (this.products.length === 0) {12throw new Error('์ฃผ๋ฌธ์ ์ต์ ํ๋์ ์ํ์ด ์์ด์ผ ํฉ๋๋ค.')13}14this.totalPrice = this.calculateTotalPrice()15}1617changeShippingAddress(newAddress: Address): void {18this.shippingAddress = newAddress19}2021completeOrder(): void {22if (this.status !== OrderStatus.PENDING) {23throw new Error('์ฃผ๋ฌธ์ ์๋ฃํ ์ ์์ต๋๋ค. Pending ์ํ๊ฐ ์๋๋๋ค.')24}25this.status = OrderStatus.COMPLETED26}2728cancelOrder(): void {29if (this.status !== OrderStatus.PENDING) {30throw new Error('์ฃผ๋ฌธ์ ์ทจ์ํ ์ ์์ต๋๋ค. Pending ์ํ๊ฐ ์๋๋๋ค.')31}32this.status = OrderStatus.CANCELED33}3435private calculateTotalPrice(): number {36return this.products.reduce((total, product) => total + product.price, 0)37}38}
- ๋๋ฉ์ธ์ ๊ฐ์ฅ ์ค์ํ ๋ ผ๋ฆฌ๋ค์ ๋ด๊ณ ์๋๋ค.
- ๊ฐ์ฅ ์ค์ํ์ง๋ง ๋จ์ํ ๋ก์ง์ผ๋ก ํ์ฌํ๋ค.
- ์ธ๋ถ ์์กด์ฑ์ด ์์ด์ผํ๋ค.
- ์ธ๋ถ์ ์์กดํ๊ฒ ๋๋ฉด ์ธ๋ถ ์์กด์ฑ์ด ๋ณ๊ฒฝ๋์๋, ๋๋ฉ์ธ์ด ํจ๊ป ๋ณ๊ฒฝ๋ผ์ผ ํ๋ค.
- ๋๋ฉ์ธ์ ์ ๋๋ก ์ธ๋ถ์ ์ํด ๋ณ๊ฒฝ ๋๋ฉด ์๋๋ค.
- ๋น์ฆ๋์ค ๋ก์ง์ ํฐ ๋ณ๊ฒฝ์ฌํญ์ด ์๋ค๋ฉด ์ด ๋ณ๊ฒฝ์ฌํญ์ ๋๋ฉ์ธ์ผ๋ก๋ถํฐ ํ์๋ผ์ผํ๋ค.
- ๋ค๋ฅธ ์ธ๋ถ ์์ ๊ฐ ๋๋ฉ์ธ์ ๋ณ๊ฒฝ์ํค๋ฉด ์๋๋ค.




- Port๋ Adapter๊ฐ ์ฐ๋ ํ ์ ์๋ ์คํ์ ๋ช
์์ด๊ธฐ ๋๋ฌธ์ ํญ์ interface ํํ๋ก ๊ตฌํํ๋ค.
- (OOP์ interface๋ฅผ ๊ผญ ์จ์ผํ๋ค๋ ์ด์ผ๊ธฐ๋ ์๋)
- ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด๋ป๊ฒ ์๋ํ ์ง ์ผ๋ฐํ๋ ์คํ (contract)๋ฅผ port์ ๋ช ์ํด๋๋ค.
- Application ๋ด๋ถ์์๋ ์ด ์คํ์ ๋ฐ๋ผ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค. ์ด ๊ตฌํ๋ ๊ธฐ๋ฅ์ Adapter๊ฐ ์ฌ์ฉํ๋ค.
- Port์ ๋ํ ์คํ์ ๋ฐ๋์ง ์๊ธฐ ๋๋ฌธ์ Application ๋ด๋ถ๋ ์ธ๋ถ ๋ก์ง์ ์ํฅ์ ๋ฐ์ง ์๋๋ค.
- ์๋ก์ด Adapter๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด,
- Port์ ์คํ์ ๋ง๊ฒ Adapter๋ง ๊ตฌํํด์ฃผ๋ฉด, Application ๋ก์ง์ ์ ํ ๊ฑด๋๋ฆด ํ์๊ฐ ์๋ค.
- Application์์ ์์
ํ ๋ก์ง์ด Driven ์ฌ์ด๋๋ก ์ด๋ป๊ฒ ์ ๋ฌ๋ ์ง ์คํ์ port์ ๋ช
์ํด๋๋ค.
- Application ๋ด๋ถ์์๋ ์ด ์คํ์ ์ฌ์ฉํ๊ณ ์ธ๋ถ์์ Port์ ๋ํ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค
2.6 Dependency Inversion
- ์ด๋ป๊ฒํ๋ฉด ๋๋ฉ์ธ์ ๊ทธ ๋ฌด์์๋ ์์กดํ์ง ์๋๋ก ๋ง๋ค ์ ์์๊น?
- ๋จ์ํ ์ง๋ฌธ์ด์ง๋ง ์ฒ์ โ์ํคํ ์ฒโ์ ๊ฐ๋ ์ ์ ํ๋ค๋ฉด ์ด๋ ค์ธ ์ ์๋ค.
- Layered Architecture๋ Top Down ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ์ธํ๋ผ๊ฐ ๋ณ๋๋๋ฉด ์ด์ฉ ์ ์์ด ๋น์ฆ๋์ค ๋ก์ง์ด ๋ณ๊ฒฝ๋๋ค.
- ์ฐ๋ฆฌ๊ฐ ์ ์ํ ํ๋ก๊ทธ๋จ์์ ORM์ TypeORM์์ Mongoose๋ก ๋ณ๊ฒฝํ๋ค๊ณ ์๊ฐํด๋ณด์.
- ๋ชจ๋ Service ๋ก์ง์ ๋ค์ ์์ฑํด์ผ ๋ ๊ฒ์ด๋ค.
- ๋น์ฆ๋์ค ๋ก์ง์ ์์น๊ฐ ์์กด์ฑ์ ๋์ด ์๋๋ฐ ์ด๋ป๊ฒ ์ด๋์๋ ์์กดํ์ง ์๊ฒ ๋ง๋ค ์ ์์๊น?
- ๋ต์ Dependency Inversion์ ์๋ค
2.7 Repository Pattern
์ ๊น ๋ค๋ฅธ ์ด์ผ๊ธฐ๋ฅผ ํด๋ณด์. ์ด๋ฏธ ์ฐ๋ฆฌ๊ฐ ์ต์ํ ์ฝ๋์ด๊ธฐ ๋๋ฌธ์ ์ดํดํ๋๋ฐ ๋์๋๋ค
- TypeORM์ ์ฐ๋ฆฌ๊ฐ ์ฐ๊ฒฐํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ด๊ณ ์์ด ๋ชจ๋ ๊ฐ์ API ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ค.
- ์ฐ๋ฆฌ๊ฐ Layered Architecture์์ ์ ์ํ ๊ฐ๋
๋ค์ ์๊ฐํด๋ณด๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ฐ๋๋ฉด ์ ๋ ์ด์ด์ ๋ก์ง์ ๋ณํ๋ฅผ ์ฃผ๊ฒ๋๋ค.
- ๊ทธ๋ฐ๋ฐ TypeORM์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํต์งธ๋ก ๋ฐ๊ฟ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ ํ ์์ ํ ํ์๊ฐ ์๋ค.
- ์ด๋ป๊ฒ ๊ฐ๋ฅํ ํ๋ง๋ฒ์ธ๊ฐ?
๐ก์์กด์ฑ ํ๋ฆ
Controller โ Service โ Repository(e.g. Postgres, MySQL, mongoDB)
2.8 Repository Pattern

- ํ๋ง๋ฒ์ interface๋ก ๊ฐ๋ฅํ๋ค.
- TypeORM์์ TypeORM๊ณผ ์ฐ๋ํ ์ ์๋ ๋ฃฐ์ interface ๋ก ์ ์ํ๋ค.
- ์ด ์ ์๋ค์ด ๋ฐ๋ก find, findOne, update, delete ๊ฐ์ ํจ์๋ค์ด๋ค.
- TypeORM์ ์ง์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ค ์ ์ด ๋ฃฐ์ ๋ง์ถฐ์ ๊ฐ ์์คํ ์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
- TypeORM์ด ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์กดํด์ผํ๋ ์ํฉ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ค์ด TypeORM ์ ์ ์๋ ๋ฃฐ ์ ์์กดํ๋ ์ํฉ์ด ๋๋ค.
- ์ด๊ฒ ๋ฐ๋ก Dependency Inversion ์ด๋ค
2.9 Dependency Inversion

3. Layered Architecture
Layered Architecture๋ ์ํํธ์จ์ด๋ฅผ ์ฌ๋ฌ๊ฐ์ ๋ ์ด์ด๋ก ๋๋๋ ์ค๊ณ๋ค.
- ๊ฐ ๋ ์ด์ด๋ณ๋ก ํนํ๋ ์์ญ์ ๋ด๋นํ๋ค.
- ๋ชจ๋ ๋ ์ด์ด๋ ๋ฐ๋ก ์๋์ ๋ ์ด์ด์๋ง ์์กดํ๋ค.
- ๋ ์ด์ด๋ฅผ ์ด๋ป๊ฒ ๋ช๊ฐ๋ก ๋๋์ง์ ๋ํ ์ ๋ต์ ์กด์ฌํ์ง ์๋๋ค.
- (ํ์ง๋ง ์ด๋์ ๋ ํ์ ์กด์ฌํ๋ค..!)

(1) Presentation Layer๋ ์ง์ญ์ ์ผ๋ก ํด์ ํ์๋ UI๋ฅผ ์๋ฏธํ๋ค.
- ํ์ง๋ง ์ํคํ ์ฒ๋ ์ด๋ค ๋ฌธ๋งฅ์ด๋ ์ ์ฉ ํ ์ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ์ต์ ๋ฐฉ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
- ์ฆ, NestJS์ ๋ฌธ๋งฅ์์๋
Controller๊ฐ ๋๋ค.
1@Controller('orders')2export class OrderController {3constructor(private readonly orderService: OrderService) {}45@Post()6async createOrder(@Body() createOrderDto: CreateOrderDto) {7return this.orderService.createOrder(createOrderDto);8}910@Get(':id')11async getOrder(@Param('id') id: string) {12return this.orderService.getOrder(id);13}14}
(2) Business Layer๋ ์ค์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ ์์ญ์ด๋ค.
- โ๋น์ฆ๋์ค ๋ก์งโ์ ๋ง ๊ทธ๋๋ก โ๋น์ฆ๋์คโ์ โ๋ก์งโ
- ์ฆ, ํ์ค ์ธ๊ณ์ ์กด์ฌํ๋ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๋ ๋ก์ง์ด๋ผ๊ณ ์๊ฐ ํ ์ ์๋ค.
- NestJS์์๋
Service๊ฐ ํด๋น๋๋ค.
1@InJectable()2export class OrderService {3constructor(4private readonly orderRepository: OrderRepository,5private readonly productRepository: ProductRepository,6) {}78async createOrder(createOrderDto: CreateOrderDto) {9const productPrices = await this.productRepository.getProductPrices();1011const order = new Order(createOrderDto.customrId, createOrderDto.items);12const total = order.calculateTotal(productPrices);1314await this.orderRepository.save(order);1516return { message: 'Order created successfully', orderId: order.id, total };17}1819async getOrder(orderId: string) {20return this.orderRepository.findById(orderId);21}22}
(3) Persistence Layer๋ ์ง์ญํ๋ฉด ์์์ฑ ๋ ์ด์ด๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ค.
- โ์์์ฑโ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์๋ฏธํ๋๊ฑธ๋ก ์๊ฐ ํ ์ ์์ง๋ง,
- ์ด ์ํฉ์์๋
Database์ ์ฐ๋ํ๋ ๋ ์ด์ด๋ค. - ๋ง์ฝ์ Database Layer๊ฐ ๋ฐ๋ก ์์๋ค๋ฉด ๋ ํฌ์ง์ ์ ๋ชจ๋ ๋งก์ ์ ๋ ์๋ค.
1@InJectable()2export class OrderRepository {3constructor(4@InjectRepository(OrderEntitiy)5private readonly repository: Repository<OrderEntity>6) {}78async save(order: Order): Promise<void> {9const orderEntity = this.repository.create({10id: order.id,11customerId: order.customerId,12items: JSON.stringify(order.items),13createdAt: order.createdAt,14})15await this.repository.save(orderEntity)16}1718async findById(orderId: string): Promise<Order | null> {19const orderEntity = await this.repository.findOneBy({id: orderId})20if (!orderEntity) return null2122return new Order(23orderEntity.customerId,24JSON.parse(orderEntity.items),25)26}27}
(4) DatabaseLayer๋ ๋ง ๊ทธ๋๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ญ์ด๋ค.
- e.g. Postgres, MongoDB, MySQL
3.1 Layered Architecture์ ๋ฌธ์
- ๋ชจ๋ ์ํคํ ์ฒ์ ๊ณตํต ๊ด์ฌ์ฌ๋ โ์์กด์ฑโ์ด๋ค. ์ด๋ค ๋ฐฉํฅ์ผ๋ก ์์กด์ฑ์ด ์ ํ๋๊ณ ์๋์ง๊ฐ ๋งค์ฐ ์ค์ํ๋ค.
Layered Architecture๋ ์์์ ์๋๋ก ์์กดํ๋ ๊ตฌ์กฐ์ด๋ค.- Top Down ๋ฐฉ์์ด ์ฌ๋์๊ฒ ๊ฐ์ฅ ์์ฐ์ค๋ฌ์ด ๊ตฌํ์ด๊ธฐ ๋๋ฌธ์,
- ํ๋ ์ํํธ์จ์ด์์
Layered Architecture๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋๋ค.
Layered Architecture๋ ๊ฒฐ๊ตญ ๋ชจ๋ ๋ ์ด์ด๊ฐ ๊ฐ์ฅ ์๋์ ์์กดํ๊ฒ ๋๊ธฐ ๋๋ฌธ์,- ์ํํธ์จ์ด ์ค๊ณ๋ฅผ ํ ๋ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ๋ถํฐ ์๊ฐํ๊ฒ ๋๋ค.
- ์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ์ํํธ์จ์ด๋ฅผ ์ฒ์ ๋ง๋ค๋๋ฅผ ์๊ฐํด๋ณด์.
- ๊ฐ์ฅ ๋จผ์ ์๊ฐํ๋๊ฑด โํ ์ด๋ธ ์ด๋ป๊ฒ ๋ง๋ค์ง?โ๋ค.
- ์ฌ๊ธฐ์ ์๋ฌธ์ด ์๊ธฐ๊ฒ ๋๋ค. ์ํํธ์จ์ด๊ฐ ํ์ด๋ด๋ ค๋ ๊ฐ์ฅ ์ค์ํ ๋ฌธ์ ๊ฐ
Business Logic- ์ฆ,
Business Layer์ ์๋ ๋ฌธ์ ๋ค์ธ๋ฐ ์ด ๋ถ๋ถ์ด ๊ณผ์ฐ ์ธ๋ถ์ ์ธ ์์ธ์ ์ํฅ์ ๋ฐ๊ฒ๋๋๊ฒ ๋ง๋๊ฒ์ธ๊ฐ?
- ์ฆ,
- ์ด๊ฒ ์๋ชป๋๋ค ์๊ฐํด์ ๋ง๋ค์ด๋ธ ์ํคํ
์ฒ๊ฐ
Clean Architecture์Hexagonal Architecture๋ค.- ์ ๋๋ก ์ ๋ต์ ์๋ค.
- Layered Architecture๋ ๋๊ตฌ๋ ์ง๊ด์ ์ผ๋ก ์ดํด ํ ์ ์๊ณ ์์ฐ์ค๋ฝ๊ฒ ์ฝ๋๋ฅผ ์์ฑ ํ ์ ์๋ค.
- ํ์ง๋ง Clean Architecture ์ Hexagonal Architecture๋ ์ฌ๊ณ ๋ฐฉ์๋ถํฐ ๋ฐ๊ฟ์ผํ๋ค.
- ๊ฒฐ๊ตญ ์ธ๋ ฅ ํธ๋ ์ด๋ ๋น์ฉ๋ ๋์ด๋๊ณ ๋จ๊ธฐ์ ์ผ๋ก ๊ฐ๋ฐ ์๊ฐ๋ ๋์ด๋๋ค.
- ์ ๋์ ์ธ ๊ฐ์๋ ์กด์ฌํ์ง ์๋๋ค.
- ์ฐ๋ฆฌ๊ฐ MSA๋ฅผ ๋ฐฐ์ฐ๋ฉฐ ๊นจ์ฐ์ณค๋ ์ ๋ค์ ๋๋์๋ณด์
4. Domain Driven Design(DDD) & Polyrepo MSA
4.1 Monorepo vs Polyrepo
- Monorepository MSA๋ ํ์ฌ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์๋๊ฒ์ฒ๋ผ ํ๋์ ๋ ํฌ์งํ ๋ฆฌ๋ก ์ฌ๋ฌ๊ฐ์ Microservice๋ฅผ ๊ฐ๋ฐํ๋ ๋ฐฉ์์ด๋ค.
- Polyrepository MSA๋ ๊ฐ๊ฐ Microservice๋ฅผ ์ํ๋ ๊ธฐ์ ์คํ์ ์ฌ์ฉํด์ ์์ ๋กญ๊ฒ ๊ฐ๋ฐํ๋ ๋ฐฉ์์ด๋ค.
- ๊ทธ ์ด๋ค ์ ์ฝ๋ ์กด์ฌํ์ง ์๊ณ ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๋ฐฐ์์จ ํต์ ๋ฐฉ๋ฒ๋ค๋ก ํ๋ก์ ํธ๋ผ๋ฆฌ ํต์ ํ๋ค.
- ํ์ฌ์ ์ธ์์ด ๋ง์์ง์๋ก Polyrepository ๋ฐฉ์์ผ๋ก ๊ฐ๋ฐ ํ ์ ๋ฐ์ ์๋ค.
- ๋๋ถ๋ถ์ ํฐ ๊ธฐ์ ๋ค์ด ์ด๋ ๊ฒ ๊ฐ๋ฐํ๊ณ ์๋ค.
- ํ์ด ๊ฐ์ฅ ์ ๋ค๋ฃจ๋ก ๊ฐ๊ฐ Microservice์ ๊ฐ์ฅ ์ ํฉํ ๊ธฐ์ ์ ์ฌ์ฉํด์ ๊ฐ๋ฐ์ ์งํ ํ ์ ์๋ค.
- ๋ชจ๋ ํ์ด ์ ๋ถ ์์ ๋กญ๊ฒ ๊ฐ๋ฐ์ ์งํํ๋ค๋ณด๋ฉด Microservice๋ฅผ ๊ธฐํํ๊ธฐ์ํ ์ผ์ข ์ ์ฝ์๊ณผ ์์คํ ์ด ํ์ํ๋ค.
- ๋ค์ํ ๋ฐฉ๋ฒ์ด ์กด์ฌํ์ง๋ง Domain Driven Design์ด ๋งค์ฐ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค
4.2 Domain Driven Design!?
- ๋ณต์กํ ๋น์ฆ๋์ค์ ์๊ตฌ์ฌํญ์ โ๋๋ฉ์ธโ์ ์ง์คํด์ ์ค๊ณํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ โ์ ๊ทผ๋ฒโ์ด๋ค.
- ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ์ถฉ์กฑํ๋ฉด์ โ์ ์ง๋ณด์โ ๊ฐ๋ฅํ๊ฒ ์์คํ ์ ์ค๊ณํ๋ ๋ฐฉ๋ฒ๋ก ์ด๋ค.
Ubiquitous Language๋ฅผ ๋งค์ฐ ๊ฐ์กฐํ๋ค.- ๊ฐ๋ฐ์๋ง ์ดํด ํ ์ ์๋ ์์ญ์ ์ต์ํ ํ๊ณ ,
- โ๋๋ฉ์ธ ์ ๋ฌธ๊ฐโ์ ํจ๊ป ์ํํธ์จ์ด๋ฅผ ์ค๊ณ ํ ์ ์๋๋ก ๋์์ธ ๋์๋ค.
- ํฐ ๊ทธ๋ฆผ์ ์ค๊ณํ๋
Strategic Design๊ณผTactical Design์ผ๋ก ๋๋๋ค. Strategic Design์ โ์ฝ๋๋ฅผ ์์ฑํ๋๋ฒโ ๋ณด๋ค ๋๋ฉ์ธ์ ์ค๊ณํ๊ณ ,- ๊ฐ๋ฐ์๊ฐ ์๋ ์ฌ๋๋ค์ด ์ค๊ณ์ ์ฐธ๊ฐ ํ ์ ์๋ ๋ฃฐ์ ์ ์ํ๊ณ ์๋ค.
Tactical Design์ DDD ๊ธฐ๋ฒ์ ์ํด ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ๋ก ์ ๋ค๋ฃจ๊ณ ์๋ค.Strategic Design์ผ๋ก ํฐ ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๊ณTactical Design์ผ๋ก ์ธ๋ถ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.Clean Architecture,Hexagonal Architecture์ โ๋๋ฉ์ธโ์ ์ ๋์์ธ ํ๊ธฐ ์ํด ํ์ํ๊ฒ ์๋๋ค.- ๊ตณ์ด ๋ฐ์ง์๋ฉด
Domain Driven Design์ด ํจ์ฌ ๋จผ์ ๊ณต๊ฐ๋์๋ค.
- ๊ตณ์ด ๋ฐ์ง์๋ฉด
Clean Architecture,Hexagonal Architecture,Microservice Architecture์ฒ๋ผ- โ๋๋ฉ์ธโ์ ์ค์ํ๋ ์์ผํฑ์ฒ๊ฐ ์ธ๊ธฐ๋ฅผ ๋๋ฉฐ
DDD๊ฐ ๋์ฑ ๊ฐ๊ด์ ๋ฐ๊ฒ ๋๋ค.
- โ๋๋ฉ์ธโ์ ์ค์ํ๋ ์์ผํฑ์ฒ๊ฐ ์ธ๊ธฐ๋ฅผ ๋๋ฉฐ
- ๋ง๋ณํต์น์ฝ์ด ์๋๋ ๋ง์๋๋ก ๋จน์ง๋ ๋ง์
4.3 Strategic Design
- ์ํํธ์จ์ด ์ค๊ณ๋ฅผ ๊ฐ์ฅ ๋์ ์์น์์ ํฐ ๊ทธ๋ฆผ์ ๊ธฐํํ๋๋ฐ ์ฌ์ฉ๋๋ค.
Ubiquitous Language๋ฅผ ์ ๋ฆฝํ๋ ๊ฐ์ฅ ์ค์ํ ์คํ ์ด์ง๋ค.- ๋๋ฉ์ธ์
์ฝ์ด ๋๋ฉ์ธ๊ณผ์๋ธ ๋๋ฉ์ธ์ผ๋ก ๋๋๋ค.์ฝ์ด ๋๋ฉ์ธ์ ํ ๋๋ฉ์ธ์ ๊ฐ์ฅ ์ค์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋๋ฉ์ธ์ด๋ค.์๋ธ ๋๋ฉ์ธ์ ์ฝ์ด๋๋ฉ์ธ ๋งํผ ์ค์ํ ๋๋ฉ์ธ์ ์๋์ง๋ง ํ์์ ์ธ ๋๋ฉ์ธ์ด๋ค.
- ์ด์ธ์
์ ๋๋ฆญ ๋๋ฉ์ธ๋ฑ ๋ค๋ฅธ ๋ถ๋ฅ๋ ์กด์ฌํ๋ค.


4.4 Tactical Design
Tactical Design์ Strategic Design ๋ณด๋ค ๋์ฑ Low Level ๊ด์ ์์ ์ค๊ณ๋ฅผ ๋ฐ๋ผ๋ณธ๋ค.- ์ฝ๋๋ฅผ ์ด๋ป๊ฒ ์์ฑํ๋ฉด ํจ์จ์ ์ผ์ง ์๋ ค์ค๋ค.
Entity โ Mutableํ ๋ฐ์ดํฐ๋ค.- ๊ผญ ID ํ๋กํผํฐ๋ฅผ ๊ฐ๊ณ ์์ผ๋ฉฐ ID๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ค๋ฅธ Entity๋ก ๊ฐ์ฃผ๋์ง๋ง,
- ๋ค๋ฅธ ํ๋กํผํฐ๊ฐ ๋ณ๊ฒฝ๋์ ๋๋ ๊ฐ์ Entity๋ก ์ธ์ํ๋ค.
Value Object(VO) โ ID๊ฐ ์กด์ฌํ์ง ์๋ค. ๊ฐ์ ๊ธฐ์ค์ผ๋ก ๊ฐ์์ง ๋ค๋ฅธ์ง ํ๋จํ๋ค.- ์๋ฅผ๋ค์ด ์ด๋ฉ์ผ์ ๊ฐ ์์ฒด๊ฐ ์ ์ฒด์ฑ์ ๋ถ๊ธฐ ๋๋ฌธ์ ID๊ฐ ๋ฐ๋ก ํ์์์ผ๋ฉฐ,
- A๊ฐ์ฒด์
test@codefactory.ai์ B ๊ฐ์ฒด์test@codefactory.ai๋ ๊ฐ์ ๊ฐ์ผ๋ก ์ธ์ํ๋ค. - Mutable์ธ Entity์ ๋ค๋ฅด๊ฒ Immutable์ด๋ค.
- Aggregate โ Entity์ Value Object๋ค์ ์์ ํ๋ ๊ฐ์ฒด๋ค. Aggregate ๋ด๋ถ์ ์๋
- Repositories โ ์ฐ๋ฆฌ๊ฐ ์๊ณ ์๋ Repository์ ๋์ผํ๋ค. ๋ฐ์ดํฐ ์์์ ์ํด ์ฌ์ฉ๋๋ ๊ฐ๋ ์ด๋ค.
- Services โ ์ฌ๋ฌ๊ฐ์ Aggregate๊ฐ ํจ๊ป ์๋ํด์ผํ๋ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ๋๋ค.
4.4 Entities & Value Objects

4.5 Aggregate & Transactional Boundary

Transactional Boundary โ Transactional Boundary์ ์ํ๋ ๊ฐ์ฒด๋ ํ๋์ Transaction์ผ๋ก ๋ณํ๊ฐ ์ผ์ด๋๋ค.
4.6 Repositories & Services

5. ๋๋ฉ์ธ์ด๋?
5.1 Microservice๋ฅผ ์ด๋ป๊ฒ ๋๋ ์ผํ๋๊ฐ?
- Microservice๋ฅผ ๋๋์ฒด ์ด๋ค ๋จ์๋ก ๋๋๋ฉด ๋๋๊ฑธ๊น?
- Microservice์ ๋ชฉ์ ์ ์๋น์ค๊ฐ์ ์์กด์ฑ์ ์ค์ด๊ณ ํจ์จ์ ์ผ๋ก ๋ ๋ฆฝ์ ๊ฐ๋ฐ์ ์งํํ๊ธฐ ์ํจ์ด๋ค.
- ๊ทธ๋ฌ๊ธฐ ์ํด์๋ ๊ฐ์ฅ ์์ ๋ ผ๋ฆฌ์ ๋จ์๋ก ์๋น์ค๋ฅผ ๋ถํด ํ ์ ์์ผ๋ฉด ๊ฐ์ฅ ํจ์จ์ ์ธ MSA๋ฅผ ์ด์ ํ ์ ์๋ค.
- ์ด ๊ฐ์ฅ ์์ ๋ ผ๋ฆฌ์ ๋จ์๋ฅผ ์ฐ๋ฆฌ๋ ํํ โ๋๋ฉ์ธโ์ด๋ผ ๋ถ๋ฅธ๋ค.
- ๋๋ฉ์ธ์ ์ค์ฌ์ผ๋ก ๊ฐ๋ฐ์ ํ๊ฒ๋๋ โDomain Driven Designโ (DDD๋ ์ข ๋์ค์ ๋ฐฐ์ฐ๋๋ก ํ์)์ด๋,
- Clean Architecture ๋ฑ์ ์ํ๋ฉด ๋๋ฉ์ธ์ ๋น์ฆ๋์ค์ ์ค์ฌ ๊ธฐ๋ฅ์ด ๋๋ ๋น์ฆ๋์ค ๋ก์ง, ํด๊ฒฐํ๋ ค๋ ์ค์ฌ๋๋ ๋ฌธ์ ๋ฑ์ผ๋ก ํํ๋๋ค.
- ๋ณดํต ์ด๋ฐ ๊ฐ๋
์ ์์ด์ ์ง์ญ์ด๊ธฐ ๋๋ฌธ์ ์ ์๊ฐ ๋ณต์กํ๊ฒ ๋๊ปด์ง์ง๋ง ์ฌ์ค ํฌ๊ฒ ์ด๋ ต์ง ์๋ค.
- ๋ค์ ์ฌ๋ผ์ด๋์์ ์์ ๋ฅผ ๋ด๋ณด๋๋ก ํด๋ณด์
5.2 ์จ๋ผ์ธ ์ผํ๋ชฐ ์์

- ๊ฐ ๋๋ฉ์ธ์ ์ฝ์ด ๋น์ฆ๋์ค ๊ธฐ๋ฅ์ ๋ด๋นํ๋ค.
- ๊ฐ๋ฐ์๊ฐ ์๋ ์ผ๋ฐ ์ฌ๋์ด ํ ๋๋ฉ์ธ์ ๋ช
์นญ์ ๋ดค์๋ ๋ฌด์จ ์ญํ ์ ํ๋์ง ์ ์ ์๊ฒ ๋ถ๋ฆฌ ํด์ผํ๋ค.
- (Domain Expert:DDD)
- ์ฒ์๋ถํฐ ์๋ฒฝํ ๋๋ฉ์ธ์ ๋๋ ํ์๊ฐ ์๋ค. ๊ฐ๋ฐํด๊ฐ๋ฉด์ ๋
๋ฆฝ ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ๋ ๋ถ๋ถ๋ค์ ๋ถ๋ฆฌํ๋ฉด ๋๋ค.
- (Shipping ๋๋ฉ์ธ์ ์ผ๋ฐ ํ๋ฐฐ, ํญ๊ณต ํ๋ฐฐ๋ฅผ ๊ฐ์ด ๊ตฌํํ๋ค๊ฐ ์๋ก ๊ด๋ จ์ฑ์ด ๋ฉ์ด์ง๊ณ
- ๋๋ฌด ์ปค์ง๋ฉด ๋์ค์ ๋๋ ๋ ๋๋ค.)
- ๋๋ฉ์ธ์ ๋ค๋ฃฐ๋๋ ๊ทธ ๋๋ฉ์ธ ํ๋์ ๊ด์ ์์ ์์
์ ํ๋ค.
- ์๋ฅผ ๋ค์ด, Order์์ Customer ๊ณ ๊ฐ์ด ์กด์ฌํ๊ณ Payment์ Payer๊ฐ ์กด์ฌํ ์ ์๋ค.
- ๋์ ๊ฐ์ ์ฌ์ฉ์๋ฅผ ์ง์นญํ์ง๋ง ์๋ก ๋ค๋ฅธ ๋๋ฉ์ธ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ ์ค๋ณต์ด ์๋๋ค.
6. CQRS Pattern
6.1 CQRS Pattern์ด๋?

CQRS Pattern์Command Query Responsibility Segregation์ด๋ค.- ์ธ์์ API๋ CRUD๋ก ๋๋๋ค (X) โ ์ธ์์ API๋ โ๋ช ๋ นโ๊ณผ โ์กฐํโ๋ก ๋๋๋ค. (O)
6.2 CQRSโฆ ๊ตณ์ด ์?
Command์Query๊ฐ ๋ ๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ ๋ ๋ฆฝ์ ์ผ๋ก ํ์ฅ ํ ์ ์๋ค.- ์๋ฅผ ๋ค์ด, ์ผํ๋ชฐ ์ฑ์ ๋ง๋ ๋ค๋ฉด ์กฐํ ์์ฒญ์ด ์๋์ ์ผ๋ก ๋ง๋ค.
- ์กฐํ ๊ธฐ๋ฅ๋ง ๋ ๋ฆฝ์ ์ผ๋ก ํ์ฅํ๊ณ ๋ช ๋ น ์์ฒญ (์ฃผ๋ฌธ๋ฑ)์ ํ์ฅํ์ง ์์ ์ ์๋ค.
- ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํด ๊ฐ๊ฐ ์ต์ ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉ ํ ์ ์๋ค.
- ํนํ, ์กฐํ ๊ธฐ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ denormalize ํ ์ํ๋ก ์ ์ฅํด๋๊ณ ,
- ์กฐํ ์์ฒญ์ด ์์๋ ๋ฐ๋ก join๋ฑ์ ๋ณต์กํ ์ฟผ๋ฆฌ ์์ด ์ฆ๊ฐ์ ์ธ ์๋ต์ ํ ์ ์๋ค.
- Command์ Query์ ๋
๋ฆฝ์ ์ธ ๋ณด์์ ์ค์ ํด์ ๊ฐ๋ฐ ํ ์ ์๋ค.
- Query๋ ์๋์ ์ผ๋ก ๋ณด์์ ์ฝํ๊ฒ ์ค์ ํ๊ณ Command๋ ์ธ์ธํ๊ฒ ๋ณด์ ์ค์ ์ ํ ์ ์๋ค.
- Microservice๋ฅผ ์ด์ํ์๋์ ์ฅ์ ๊ณผ ๋จ์ ์ด ๊ฑฐ์ ์์๋๋ค.
6.3 CQRS

6.4 Event Driven Architecture
