Upgrade to Pro — share decks privately, control downloads, hide ads and more …

모놀리스 시스템 분할과 정복

Arawn Park
August 12, 2024

모놀리스 시스템 분할과 정복

모놀리스 아키텍처는 단일 코드베이스와 개발 환경을 사용하여 모든 서비스 구성 요소를 하나의 애플리케이션으로 통합하므로 개발, 배포 및 관리 과정이 단순합니다. 또한, 새로운 개발자가 개발에 참여할 때 전체 시스템의 구조를 이해하기가 비교적 용이합니다. 그러나 시스템이 커질수록 '거대한 진흙 덩어리 Big ball of mud' 현상이 발생하며 유지보수가 어려워지고 비즈니스 환경 변화에 대한 대응력이 떨어집니다.

이러한 문제를 해결하기 위해 모듈을 이용하면 시스템의 구조를 이해하기 위해 한 번에 고려해야 하는 요소의 수를 줄일 수 있기 때문에 전체적인 복잡도를 낮출 수 있습니다. 각 모듈은 독립적으로 개발, 테스트 및 유지관리 하며 시스템은 여러 모듈의 상호작용을 통해 작동합니다. 모듈은 각자의 책임과 기능에 따라 분할하고 명확하게 정의된 인터페이스를 통해 다른 모듈과 최소한의 의존성을 유지하며 상호작용을 해야 합니다.

이처럼 모듈화를 통해 시스템 복잡성을 효과적으로 관리하고 변화에 유연하게 대응하며 지속 가능한 방식으로 시스템을 진화시킬 수 있습니다. 이러한 특징을 가진 구조를 모듈형 모놀리스(Modular Monolith)라고 합니다.

모듈형 모놀리스는 전통적인 모놀리스의 단순성과 모듈화의 이점을 결합한 실용적인 아키텍처 스타일입니다. 단일 코드베이스와 배포 단위를 유지하면서도 시스템을 명확한 책임과 경계를 가진 자율적인 모듈로 분할하여 개발, 테스트 및 유지관리를 쉽게 합니다. 모듈은 비즈니스 기능 단위로 구성되는 수직 슬라이스 방식으로 분할하고, 각 모듈 내부는 사용자 인터페이스부터 비즈니스, 데이터 등 필요한 만큼 계층화를 통해 복잡성을 관리합니다.

이처럼 모듈형 모놀리스는 시스템 복잡성을 효과적으로 관리하면서도 유지보수성과 유연성을 확보할 수 있습니다. 특히, 빠르게 변화하는 비즈니스 환경에 민첩하게 대응해야 하는 현대 소프트웨어 개발 환경에서 꽤 매력적인 선택지가 될 수 있습니다.

본 자료는 개인적인 경험과 견해를 바탕으로 모듈형 모놀리스 시스템의 설계부터 구현까지 과정을 공유하기 위해 작성되었습니다.

Arawn Park

August 12, 2024
Tweet

More Decks by Arawn Park

Other Decks in Programming

Transcript

  1. ] ઱ਃইఃఫ୊Ѿ੿ۨ௏٘ "SDIJUFDUVSF%FDJTJPO3FDPSE"%3 . ├─ docs │ ├─ architecture-decision-records │

    │ ├─ 0001-record-architecture-decisions │ │ ├─ 0002-use-modular-monolith-system-architecture │ │ ├─ 0003-divide-the-system-into-4-modules │ │ ├─ 0004-use-java-spring-and-gradle-multi-project │ │ ├─ 0005-create-one-spring-boot-application │ │ ├─ 0006-use-api-design-first-approach │ │ ├─ 0007-use-3-layered-architecture-style │ │ ├─ 0008-use-openapi-generator-for-presentation-layer │ │ ├─ 0009-add-unit-testing-for-modules │ │ ├─ 0010-create-domain-models-and-service-layer-in-domain-layer │ │ ├─ 0011-use-command-query-separation-principle │ │ ├─ 0012-use-domain-driven-design-tactical-design │ │ ├─ 0013-use-uuid-as-domain-models-identifier-for-persistence │ │ ├─ 0014-use-spring-data-for-data-layer │ │ ├─ 0015-create-an-database-per-modules │ │ ├─ 0016-use-token-based-authentication │ │ ├─ 0017-use-gradle-convention-plugins │ │ ├─ 0018-add-integration-testing │ │ ├─ 0019-use-anti-corruption-layer-pattern │ │ ├─ 0020-use-java-platform-module-system │ │ ├─ 0021-create-an-spring-ioc-container-per-modules │ │ ├─ 0022-add-system-testing │ │ ├─ 0023-create-an-inter-modules-communication-library │ │ ├─ 0024-use-event-driven-architecture-style │ │ └─ 0025-use-outbox-and-inbox-pattern │ ├─ comments │ └─ images ├── applications ├── modules ├── libraries ├── tests ├── gradle.properties ├── settings.gradle └── gradlew ࣗ೐౟ਝযदझమࢸ҅җ੿ীࢲղ۰૓઺ਃೠѾ੿җ Ӓ੉ਬܳޙࢲചೞৈైݺࢿҗ୶੸ࢿਸ֫੉חӝ۾੉׮
  2. ] %JWJEFUIFTZTUFNJOUPNPEVMFT . ├── applications │ └── coffeehouse-server ├── modules

    │ ├── brew │ ├── catalog │ ├── order │ └── user ├── libraries │ ├── base │ ├── security │ ├── spring-extensions │ └── spring-data-extensions ├── gradle.properties ├── settings.gradle └── gradlew Ӓۨ੉ٜݣ౭೐۽ં౟ߑधਵ۽೐۽ં౟ٜܳ݅Ҋ ׮ࣻ੄ݽٕҗ૓ੑ੼৉ೡਸࣻ೯ೡগ೒ܻா੉࣌ਸ੿੄೮׮ ✔ 바운디드 컨텍스트 ✔ 이벤트 스토밍 ✔ 사용자 스토리 매핑 ✔ 워크플로 접근법 ✔ 등등... ^
  3. ] ؘ੉ఠ҅கীݒಌܳߓ஖೧بݫੋ੄ة݀ࢿਸࠁ੢ೠ׮ VTFSJOUFSGBDFBQJ 1SFTFOUBUJPO TFSWJDFEPNBJO %PNBJO NBQQFS  EBUBBDDFTT %BUB

    0SEFSNPEVMF VTFSJOUFSGBDFBQJ 1SFTFOUBUJPO TFSWJDFEPNBJO %PNBJO EBUBBDDFTT %BUB 0SEFSNPEVMF ੄ઓҙ҅৉੹ਗ஗੸ਊೠ׮
  4. ] "EE6OJU5FTUJOHGPS.PEVMFT #SFX.PEVMF 0SEFS.PEVMF 6TFS.PEVMF $BUBMPH.PEVMF VOJUUFTUT . ├── applications

    │ └── coffeehouse-server ├── modules │ ├── brew │ ├── catalog │ ├── order │ └── user │ ├── src │ │ ├── main │ │ └── test │ ├── user.0.0.oas.yaml │ └── build.gradle ├── libraries │ ├── base │ ├── security │ ├── spring-extensions │ └── spring-data-extensions ├── gradle.properties ├── settings.gradle └── gradlew пݽٕ੉੄بೠӝמਸ উ੿੸ਵ۽୊ܻೞח૑Ѩૐೠ׮
  5. ] $SFBUF%PNBJO.PEFMBOE4FSWJDF-BZFSJO%PNBJOMBZFS ^ ✔ 도메인 모델 ✔ 트랜잭션 스크립트 ✔

    테이블 데이터 ✔ 등등... VTFSJOUFSGBDFBQJ 1SFTFOUBUJPO TFSWJDFEPNBJO %PNBJO NBQQFS  SFQPTJUPSZEBP %BUB 0SEFSNPEVMF
  6. ] 1PG&""بݫੋݽ؛ https://martinfowler.com/eaaCatalog/domainModel.html . ├─ applications ├─ modules │ ├─

    brew │ ├─ catalog │ ├─ order │ └─ user │ ├─ src │ │ ├─ main │ │ │ ├─ web │ │ │ ├─ domain │ │ │ │ ├─ entity │ │ │ │ └─ service │ │ │ └─ data │ │ └─ test │ ├─ user.0.0.oas.yaml │ └─ build.gradle ├─ libraries ├─ gradle.properties ├─ settings.gradle └─ gradlew ё୓ٜ੉بݫੋ֤ܻܳ಴അೞҊҳഅೞחߑध੉׮
  7. ] 1PG&""ࢲ࠺झ҅க https://martinfowler.com/eaaCatalog/serviceLayer.html . ├─ applications ├─ modules │ ├─

    brew │ ├─ catalog │ ├─ order │ └─ user │ ├─ src │ │ ├─ main │ │ │ ├─ web │ │ │ ├─ domain │ │ │ │ ├─ entity │ │ │ │ └─ service │ │ │ └─ data │ │ └─ test │ ├─ user.0.0.oas.yaml │ └─ build.gradle ├─ libraries ├─ gradle.properties ├─ settings.gradle └─ gradlew بݫੋݽ؛ٜ੉ਗഝೞѱഈ۱ೞҊ গ೒ܻா੉࣌੄੹߈੸ੋ൒ܴਸઁযೡࣻ੓ب۾ذח׮
  8. ] ా೤ػݽٕр࢚ഐ੘ਊѨૐ੉೙ਃೞ׮ #SFX.PEVMF 0SEFS.PEVMF 6TFS.PEVMF $BUBMPH.PEVMF 0SEFS1MBDFNFOU1SPDFTTPSKBWB class OrderPlacementProcessor implements

    OrderPlacement { Customers customers; Catalogs catalogs; OrderRepository orderRepository; OrderPlacementProcessor(...) { ... } OrderId placeOrder( UserAccountId customerId, List<OrderLine> orderLines ) { // Ҋё ߂ ࢚ಿ ੿ࠁ ࠛ۞য়ӝ // ઱ޙ ࢤࢿ
 return orderId; } }
  9. ] "EE*OUFHSBUJPO5FTUJOH #SFX.PEVMF 0SEFS.PEVMF 6TFS.PEVMF $BUBMPH.PEVMF JOUFHSBUJPOUFTUT . ├─ applications

    │ └─ coffeehouse-server ├─ modules │ ├─ brew │ ├─ catalog │ ├─ order │ │ └─ src │ │ ├─ main │ │ └─ test │ └─ user ├─ libraries │ ├─ base │ ├─ security │ ├─ spring-extensions │ └─ spring-data-extensions ├─ tests │ └─ integration-testing ├─ gradle.properties ├─ settings.gradle └─ gradlew ݽٕрా೤߂৻ࠗઙࣘࢿҗ੄ ࢚ഐ੘ਊਸѨૐೠ׮
  10. ] ݽٕръѾ೤਷ݽٕة݀ࢿਸ೧஘׮ DBUBMPH <<Interface>> ProductRepository OrderPlacementProcessor <<Interface>> OrderPlacement PSEFS JdbcProductRepository

    CatalogsService <<Interface>> Catalogs ݽٕղبݫੋ҅கীࢲ׮ܲݽٕ੄"1*ܳ ૒੽ଵઑೞҊ੓׮ NPEVMF class OrderPlacementProcessor { catalogs.getProductDetails(productId); ... }
  11. ] 6TF"OUJ$PSSVQUJPO-BZFSQBUUFSO 0SEFS$POUFYU #SFX $POUFYU XFC EPNBJO EBUB $BUBMPH $POUFYU

    6TFS $POUFYU . ├─ applications │ └─ coffeehouse-server ├─ modules │ ├─ brew │ ├─ catalog │ ├─ order │ │ ├─ src/main/java/... │ │ │ ├─ integrate │ │ │ ├─ web │ │ │ ├─ domain │ │ │ └─ data │ │ ├─ order.0.0.oas.yaml │ │ └─ build.gradle │ └─ user ├─ libraries ├─ tests │ └─ integration-testing ├─ gradle.properties ├─ settings.gradle └─ gradlew "OUJ$PSSVQUJPO-BZFS https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer
  12. ] ࢚ࣚߑ૑҅க਷ా೤җ߸ജਸ୊ܻೠ׮ . ├─ applications │ └─ coffeehouse-server ├─ modules

    │ ├─ brew │ ├─ catalog │ ├─ order │ │ ├─ src/main/java/... │ │ │ ├─ integrate │ │ │ ├─ web │ │ │ ├─ domain │ │ │ └─ data │ │ ├─ order.0.0.oas.yaml │ │ └─ build.gradle │ └─ user ├─ libraries ├─ tests │ └─ integration-testing ├─ gradle.properties ├─ settings.gradle └─ gradlew 0SEFS1MBDFNFOU1SPDFTTPSKBWB class OrderPlacementProcessor implements OrderPlacement { OrdererVerification ordererVerification; OrderItemFactory orderItemFactory; OrderId placeOrder(...) { ordererVerification.verify(...) orderItemFactory.create(...) } } 0SEFS1MBDFNFOU"EBQUFSKBWB class OrderPlacementAdapter implements OrdererVerification , OrderItemFactory { Customers customers; Catalogs catalogs; }
  13. ] ݽٕղҳഅࣁࠗࢎ೦ਸ߆ীࢲঌইࢶউػ׮ DBUBMPH <<Interface>> ProductRepository OrderPlacementAdapter <<Interface>> OrderItemFactory PSEFS JdbcProductRepository

    NPEVMF CatalogsService <<Interface>> Catalogs ݽٕղ࢚ࣚߑ૑҅கীࢲ׮ܲݽٕ੄ ҳഅࣁࠗࢎ೦ਸ૒੽ଵઑೞҊ੓׮
  14. ] DBUBMPH <<Interface>> ProductRepository OrderPlacementAdapter <<Interface>> OrderItemFactory PSEFS JdbcProductRepository NPEVMF

    CatalogsService <<Interface>> Catalogs оदࢿਵ۽ஹನք౟ܳਟ݅ఀࠁഐೡࣻ੓׮ QVCMJD QSPUFDUFE EFGBVMU QBDLBHF  QSJWBUF QVCMJD
  15. ] оदࢿਵ۽ஹನք౟ܳਟ݅ఀࠁഐೡࣻ੓׮ DBUBMPH <<Interface>> ProductRepository OrderPlacementAdapter <<Interface>> OrderItemFactory PSEFS JdbcProductRepository

    NPEVMF CatalogsService <<Interface>> Catalogs QVCMJD ҕѐ QVCMJD ػੋఠಕ੉झח঱ઁٚࢎਊೡࣻ੓׮ . ├─ web ├─ domain │ ├─ entity │ │ ├─ Product.java │ │ └─ ProductRepository.java │ ├─ service │ │ └─ Catalogs.java │ └─ CatalogException.java └─ data
  16. ] 6TF+BWB1MBUGPSN.PEVMF4ZTUFN DBUBMPH <<Interface>> ProductRepository JdbcProductRepository CatalogsService <<Interface>> Catalogs FYQPSUT

    NPEVMFJOGPKBWB module coffeehouse.modules.catalog { requires coffeehouse.libraries.base; exports coffeehouse.modules.catalog.domain; exports coffeehouse.modules.catalog.domain.service; } . ├─ web ├─ domain │ ├─ entity │ │ ├─ Product.java │ │ └─ ProductRepository.java │ ├─ service │ │ └─ Catalogs.java │ └─ CatalogException.java ├─ data └─ module-info.java ҕѐೡੋఠಕ੉झ৬ࢎਊೡ੄ઓࢿҙܻܳా೧ ੗ਯ੸ੋݽٕҙܻܳ૑ਗೠ׮
  17. ] "EE4ZTUFN5FTUJOH #SFX.PEVMF 0SEFS.PEVMF 6TFS.PEVMF $BUBMPH.PEVMF TZTUFNUFTUT . ├── applications

    │ └── coffeehouse-server ├── modules │ ├── brew │ ├── catalog │ ├── order │ └── user ├── libraries ├── tests │ ├── integration-testing │ └── system-testing │ ├── src │ ├── docker-compose.yaml │ └── build.gradle ├── gradle.properties ├── settings.gradle └── gradlew EPDLFSDPNQPTFVQSVOUFTUT
  18. ] $SFBUFBO*OUFSNPEVMFT$PNNVOJDBUJPO-JCSBSZ 6TFS.PEVMF 0SEFS.PEVMF NPEVMFNFTI <<Interface>> ModuleFunctionRegistry <<Interface>> ModuleFunctionOperations DefaultModule


    FunctionOperations <<Interface>> ObjectMapper registry.registerModuleFunction("customers/get-customer-details", CustomerDetails.class) operations.execute("customers/get-customer-details", Orderer.class) $VTUPNFS%FUBJMTDMBTT UP 0SEFSFSDMBTT
  19. ] 6TF&WFOU%SJWFO"SDIJUFDUVSF4UZMF 0SEFS.PEVMF #SFX.PEVMF NPEVMFNFTI <<Interface>> ModuleEventPublisher Application ModuleEventProcessor <<Interface>>

    ObjectMapper eventPublisher.publishEvent(OrderAcceptedEvent.of(orderId)) eventListener.on(orderAcceptedEvent) 0SEFS0SEFS"DDFQUFE&WFOUDMBTT UP #SFX0SEFS"DDFQUFE&WFOUDMBTT
  20. ] ݽٕഋݽ֥ܻझ ҕѐ ੋఠಕ੉झ ҕਬੋ೐ۄझ౟۟୊ ݽٕ ݽٕా೤೐۽ࣁࢲ ✔ 단일 배포

    단위 ✔ 내부 모듈성 ✔ 공유 인프라스트럭처 ױੌߓನױਤ ੹ా੸ੋݽ֥ܻझইఃఫ୊੄ ױࣽࢿҗݽٕച੄੉੼ਸѾ೤ೠ ইఃఫ୊झఋੌ੉׮
  21. ] ݽٕഋݽ֥ܻझо঳ਸࣻ੓חഌఖ ਬ૑ ࠁࣻࢿ ݽٕࢿ ױࣽࢿ ਬোࢿ ࢿמ ബਯࢿ ҕѐ

    ੋఠಕ੉झ ҕਬੋ೐ۄझ౟۟୊ ݽٕ ݽٕా೤೐۽ࣁࢲ ױੌߓನױਤ
  22. 5IF HPBM PG TPGUXBSF EFMJWFSZ JT UP NJOJNJ[F UIF MFBE

    UJNFUPCVTJOFTTJNQBDU&WFSZUIJOHFMTFJTEFUBJM %BO/PSUI IUUQTEBOOPSUIOFUBSFXFOFBSMZUIFSFZFU
  23. ] ଵҊ੗ܐ ✓ Modular Monolith Architecture ✓ Building modular monolith

    using spring ✓ 엔터프라이즈 애플리케이션 아키텍처 패턴 ✓ 클린 아키텍처 ✓ Vertical Slice Architecture ✓ 도메인 주도 설계 핵심 ✓ 오브젝트: 코드로 이해하는 객체지향 설계 ✓ 마이크로서비스 아키텍처 구축 ✓ OpenAPI와 스웨거를 활용한 실전 API 설계 ✓ 자바 9 모듈 프로그래밍 ✓ 이펙티브 소프트웨어 테스팅 ✓ 단위 테스트 ✓ The Nature of Software Development
 ✓ 단순한 아키텍처를 옹호하며