07.CQRS
๋ณต์กํ ์กฐ๊ฑด์ผ๋ก ํํฐ๋ง
ํ๊ฑฐ๋ ๋ค์ํ ์ง๊ณ
์๊ตฌ์ฌํญ์ ์ถฉ์กฑ์ํค๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ช
๋ น๊ณผ ์กฐํ ์ฑ
์ ๋ถ๋ฆฌ(CQRS)๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด๋ฒคํธ ์์ฑ์ ์ฌ์ฉํ ์์คํ ์์ CQRS๋ ์ ํ์ด ์๋ ํ์
CQRS๋ ํ์ฌ ์ํ๋ง ๊ธฐ๋กํ๋ ์์คํ ์์๋ ์ ์ฉํ๊ฒ ํ์ฉ ๊ฐ๋ฅ
๋ช
๋ น๊ณผ ์กฐํ ์ฑ
์ ๋ถ๋ฆฌ
CQS
๋ ๊ฐ์ฒด๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋ค๋ฅด ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ์ปค๋งจ๋
์ ์ํ๋ฅผ ๋ฐํํ๋ ์ฟผ๋ฆฌ
๋ก ๊ตฌ๋ถ
CQS and CQRS

CQRS
๋ ๋ง์ ํ ์ด๋ธ ์กฐ์ธ์ ํผํ๊ธฐ ์ํด ์กฐํ์ ์ต์ ํ์ํจ ํ ์ด๋ธ์ ๋ถ๋ฆฌํด์ ์ค๊ณํ๊ณ ์ปค๋งจ๋ ์ฒ๋ฆฌ๋ฅผ ์๋ฃํ ํ ๋ฐํํ ๋๋ฉ์ธ ์ด๋ฒคํธ์์ ํ์ํ ์์ฑ์ ๋ณต์ฌํด ์กฐํ ์ ์ฉ ํ ์ด๋ธ์ ํ๋ฒ ๋ CUD๋ฅผ ์คํ
๊ตฌ์ฒดํ๋ ๋ทฐ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ
๋ทฐ๊ฐ ๋ ผ๋ฆฌ์ ์ธ ํ ์ด๋ธ์ธ ๋ฐ๋ฉด ๊ตฌ์ฒดํ๋ ๋ทฐ(Materialized View)๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์กด์ฌํ๋ ํ ์ด๋ธ
๊ตฌ์ฒดํ๋ ๋ทฐ๋ ์ฃผ๋ก ๋ณต์กํ ์กฐ์ธ๊ณผ ๊ฐ์ด ๋ง์ ๋น์ฉ์ด ๋๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋ ์ฌ์ฉ
๊ตฌ์ฒดํ๋ ๋ทฐ๋ฅผ ์์ฑํ ๋ AVG, SUM, COUNT ๊ฐ์ ์ง๊ณ ํจ์๋ฅผ ์ฌ์ฉํด ๋ค์ํ ์กฐ๊ฑด์ ์ฌ์ฉ ๊ฐ๋ฅ

.
๋ทฐ์ ๊ตฌ์ฒดํ๋ ๋ทฐ์ ํน์ง๊ณผ ์ฐจ์ด์
๋ทฐ
๋ทฐ๋ ๋ฏธ๋ฆฌ ๋ค์ด๋ฐํ ์ฟผ๋ฆฌ๋ก ์ด๋ค ๊ฒ๋ ์ถ๊ฐ ์ ์ฅ ๋ถ๊ฐ
๋ทฐ์ ์ง์ํ๋ฉด ๋ทฐ ์ ์์ ๊ธฐ๋ฐํด ์ค์ ํ ์ด๋ธ์ ๋ฐ์ดํฐ ์กฐํ
๋ทฐ๋ ํ ์ด๋ธ ์ฟผ๋ฆฌ๋ณด๋ค ๋๋ฆผ
์๋์ ๋ณต์กํ ์ฟผ๋ฆฌ๋ฌธ์ ๋ทฐ ์ ์๋ก ์ด๋ํ ๋ฟ ์ ์ง๋ณด์ ๋น์ฉ์ ๊ฐ์ํ์ง ์์
๊ตฌ์ฒดํ๋ ๋ทฐ
๊ตฌ์ฒดํ๋ ๋ทฐ๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ฃผ๊ธฐ์ ์ผ๋ก ๊ฐฑ์
๊ตฌ์ฒดํ๋ ๋ทฐ์ ์ง์ํ๋ฉด ๊ตฌ์ฒดํ๋ ๋ทฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ
JSON์ ํฌํจํด ๋ค์ํ ์กฐ๊ฑด์ SELECT ์ฟผ๋ฆฌ๋ฅผ ์ํ ๋น ๋ฅธ ์ฑ๋ฅ์ ์ ๊ณต
์ฟผ๋ฆฌ ์ตํฐ๋ง์ด์ ๊ฐ ์คํ ๊ณํ์ ์๋ฆฝํ ๋ ๋ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ ์ ํ
.
CQRS ํต์ฌ ๊ฐ์ฒด์ ์์กด์ฑ
๊ตฌ์ฒดํ๋ ๋ทฐ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ํ ๊ตฌ์ฑ ์์๊ฐ ๊ด๊ณ

์ ๊ทธ๋ฆฌ๊ฒ์ดํธ๊ฐ ๋๋ฉ์ธ ์ด๋ฒคํธ๋ฅผ ๋ฐํํ๋ฉด ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ด๋ฒคํธ์ ๋ฐ์ํด ๋ทฐ ๊ฐ์ฒด๋ก ๋ณํ
ViewStore๋ ๋ทฐ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฒดํ๋ ๋ทฐ ํ ์ด๋ธ๊ณผ ๋งคํํ JPA ์ํฐํฐ ๊ฐ์ฒด๋ก ๋ณํํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
์กฐํ ๋ชฉ์ ์ ๋ฐ๋ผ ๊ฐ๋ณ ํ ์ด๋ธ๋ก ๋ถ๋ฆฌํด ์ค๊ณํ๊ฑฐ๋ ๋์ผ ์กฐํ ์กฐ๊ฑด์ ๊ฐ์ง ์ฌ๋ฌ ๋ทฐ ํด๋์ค๋ฅผ ํ๋์ ํ ์ด๋ธ๋ก ํตํฉ ๊ฐ๋ฅ
.
์ํ ํ๋งค๋ ๋ทฐ
์ฃผ๋ฌธ ์ ๊ทธ๋ฆฌ๊ฒ์ดํธ๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ๋ฉ์์ง ๋ฆด๋ ์ด๊ฐ OrderCompleted ๋๋ฉ์ธ ์ด๋ฒคํธ๋ฅผ ๋ฐํ
OrderCompleted ์ด๋ฒคํธ์ ๋ฐ์ํ๋ ProductOrderViewHandler๋ ์ํ๋ณ ํ๋งค ์๋ ์์ฑ์ ํฌํจํ๋ ProductORderView๋ฅผ ์์ฑํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
๋ฐ๋๋ก ์ฃผ๋ฌธ์ ์ทจ์ํ๋ฉด ํด๋น ์ํ ํ๋งค๋ ๋ทฐ๋ฅผ ์ญ์
ProductOrderViewHandler๋ OrderCanceled ์ด๋ฒคํธ์ ๋ฐ์ํด OrderNo๋ก ๋ทฐ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ฐพ์ ์ญ์
.
์๋ด์ฌ ์ผ์ผ ์ด ํตํ์๊ฐ ๋ทฐ
ํตํ๋ฅผ ์์ํ๋ฉด BeginCall ์ปค๋งจ๋๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๋ ์์ฑ์๋ฅผ ํธ์ถ
์์ฑ์๋ Talktime ๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ ํ์ฌ ์๊ฐ์ start ๊ฐ์ผ๋ก ํ ๋น
ํตํ๋ฅผ ์ข ๋ฃํ๋ฉด end ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ Talktime์ end์ ํ์ฌ ์๊ฐ์ ํ ๋นํ๋ฉด์ ํตํ์๊ฐ์ ๊ณ์ฐํด CallEnded ์ด๋ฒคํธ์ ํฌํจ
์กฐํ ์์ฒญ์ ๋จ์ SELECT๋ง ์ฌ์ฉํ๋ฏ๋ก ๋ฐฑ์๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํฐ ๋ถํ๊ฐ ์์
๋ฐ๋๋ก ์ ํ ์๋ด์ฌ๊ฐ ํตํ ์ข ๋ฃ ์ ์กฐํ ์ ์ฉ ํ ์ด๋ธ์ ์ ๋ฐ์ดํธํ๋ ๋ฐ ์ฌ์ฉํ๋ ๋น์ฉ์ ๊ฐ์ ํด์ผ ํ ๋์
์ด๋ ๋ฉ์์ง ๋ธ๋ก์ปค์ ๋๋ฉ์ธ ์ด๋ฒคํธ๋ฅผ ๋ฐํํด์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ๋ฉด ๋ ๊ธฐ๋ฅ์ ์คํ ์๊ฐ์ ๋ถ๋ฆฌ ๊ฐ๋ฅ
๋ทฐ ์กฐํ
์กฐํ๋ฅผ ์ํ ํด๋์ค๋ ์ ๋์ด๋ก Query๋ฅผ ์ฌ์ฉ
@RestController
@RequestMapping("/cart")
class CartEndpoint(
private val httpSession: HttpSession,
private val cartService: CartService,
private val cartViewStore: CartViewStore
) {
@GetMapping(headers = ["query=QueryCart"])
fun queryCart(): Cart {
return cartService.queryCart()
}
@GetMapping(headers = ["query=QueryCartItem"])
fun queryItem(@RequestParam itemId: String): ItemView {
val userId = httpSession.getAttribute("userId")?.toString() ?: throw IllegalStateException("User not logged in")
val query = QueryCartItem(userId, itemId)
return cartViewStore.queryItem(query)
}
}
๋ทฐ ๋ณต์
์กฐํ ์ ์ฉ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํด๋ ์ด๋ฒคํธ ์คํ ์ด์ ๋ชจ๋ ๋๋ฉ์ธ ์ด๋ฒคํธ๊ฐ ์ ์ฅ๋์ด ์์ผ๋ฏ๋ก ํ์ ์ ๋ค์ ์กฐํ ์ ์ฉ ๋ฐ์ดํฐ๋ฅผ ์์ฑ ๊ฐ๋ฅ
ViewRecover๊ฐ ์ด๋ฒคํธ ์ ์ฅ์์์ ๋๋ฉ์ธ ์ด๋ฒคํธ ์กฐํ ํ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ ๋ฌํด ์ค์๋ก ์ญ์ ํ ์ฟ ์ฒดํ๋ ๋ทฐ๋ฅผ ๋ค์ ์์ฑ

๋ง์ดํฌ๋ก์๋น์ค ๋ชจ๋
CQRS๋ฅผ ์ ์ฉํ ๋ง์ดํฌ๋ก์๋น์ค์ ๋ชจ๋์ view
view
ํจํค์ง๋ ์กฐํ ์ ์ฉ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ณ๊ฒฝํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ํด๋์ค๋ฅผ ํฌํจ์กฐํ๋ฅผ ์ํ ํด๋์ค๋
query
ํจํค์ง์ ์์น

๋ง์ดํฌ๋ก์๋น์ค์์ ์ฌ๋ฌ ๊ฐ์ ๋ทฐ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค๋ฉด view ํ์ ํจํค์ง์ ์ถ๊ฐํ์ฌ ๊ตฌ๋ถ

CQRS ํ์ฉ ์ฌ๋ก
์ด๋ฒคํธ ์ฃผ๋ ์ํคํ ์ฒ๋ ์ด๋ฒคํธ๋ฅผ ํ์ฉํด ์๋น์ค ๊ฐ์ ์์กด์ฑ์ ์ต์ํํด ๋์จํ๊ฒ ๊ฒฐํฉํ ์์คํ ์ ๊ตฌ์ถํ ์ ์๊ฒ ํ๋ค.
๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ์์ ์ด๋ฒคํธ๋ฅผ ์ ๊ทน์ ์ผ๋ก ๋์ ํ๋ฉด ๋ค์ํ ์กฐํ ๊ธฐ๋ฅ์ ์ถ๊ฐ/๋ณ๊ฒฝ์ด ์์ ๋ก์ ํ์ฅ์ฑ์ ๋์ด๋ฉด์ ๋ ๋ฆฝ์ ์ธ ๊ฐ์ ์ด ๊ฐ๋ฅ
์ด๋ฒคํธ ์์ฑ๊ณผ ๋ทฐ ์ผ๊ด์ฑ
CQRS ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํธ๋์ญ์ ๋ถ๋ฆฌ
์ด๋ฒคํธ ์์ฑ์์ ๋น์ฆ๋์ค ๋ก์ง์ ์ ๊ทธ๋ฆฌ๊ฒ์ดํธ๊ฐ ์ฒ๋ฆฌํ๊ณ ํ ์ด๋ธ๋ค์ ์กฐ์ธํด ์กฐํํ๋ ์ฑ ์์ CQRS๋ก ๋ถ๋ฆฌ
CQRS์์ ์กฐํ ์ ์ฉ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ์์น์ ์ผ๋ก ๋น๋๊ธฐ๋ก ๋ฐ์ํด์ผ ํจ

CQRS ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ํธ๋์ญ์ ํตํฉ
ํ ํธ๋์ญ์ ์ผ๋ก ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํ๋์ ํธ๋์ญ์ ์์ ์ฒ๋ฆฌ๋จ์ ๋ณด์ฅ
๋จ, ํ ํธ๋์ญ์ ์ฒ๋ฆฌ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด ๋จ์ผ ๋ง์ดํฌ๋ก์๋น์ค์์๋ง ์ฌ์ฉํ ์ ์๋ ๋จ์
์์ฝ
Last updated