Skip to content

witherview 를 멀티 모듈 프로젝트로 구성하기  #33

@MoonYeeun

Description

@MoonYeeun

AS-IS:

현재 위더뷰는 모놀리틱 그 자체이다.

스크린샷 2021-06-06 오후 5 03 19

현재의 문제

  • 서비스가 점점 커져갈수록 하나의 어플리케이션에서 너무 많은 일들을 감당하게됨

  • 선택적 확장이 불가능

  • 하나의 서비스가 모든 서비스에 영향을 줌

    • 실제로 Mysql DB, rabbitMQ, Redis 등 외부 자원에 문제가 생겼을 때 관련 서비스만 영향받는 것이 아니라 어플리케이션 자체가 실행이 안됨
  • 등등

이 문제를 어떻게 해결할 것인가?

  • MSA로 서버들을 다 분리하자니 현재 유저를 중심으로 모든 관계가 엮여있음

    단독 서버로 띄우기 위해서는

    • 하나의 서버에서 유저 중심 관계를 모두 가져간 후, 필요한 부분을 다른 서버에서 api 요청을 통해 다 받아온다. ⇒ 비효율

    • 각 서버마다 관계로 엮인 부분을 동일하게 구현하여 사용한다. ⇒ 중복코드 너무 많, 비효율

    즉, 지금 상황에서 MSA 로 바꾸는 것은 오히려 비효율적임

  • 그렇다면 MSA 처럼 모든 서버를 독립적으로 띄우는 것 말고 공통 부분은 최소한으로 유지하면서 분리되어야 하는 부분은 따로 관리할 수 있는 방법이 없을까?

    = 멀티 모듈로 프로젝트 구성하기

TO-BE:

멀티 모듈로 위더뷰 프로젝트를 구성한다.

멀티 모듈 프로젝트는 하나의 시스템을 단위로 만든다.

여기서 말하는 시스템은 아래와 같은 정의를 말한다.

system

  • 모듈이란 독립적으로 운영될 수 있는 의미를 가지는 구성요소 단위이다.
  • 멀티 모듈 프로젝트는 독립적으로 실행가능한 어플리케이션 모듈을 1개 이상 가지고 있으며, 사용하는 인프라 자원 역시 1개 이상을 가지고 있다.
  • 독립적으로 실행 가능 한 어플리케이션들은 당연히 서로 다른 책임과 역할을 가지기 때문에 하위의 모듈들에 대한 의존성과 사용성에 대한 개방, 폐쇄를 철저히 해야한다.

출처: 우아한 형제들 - 멀티 모듈 설계 이야기

사실 현재 위더뷰 내부에서 도메인 별로 관리를 하고 있는데 굳이 멀티 모듈로 변경할 필요가 있을까? 라는 생각이 들 수도 있지만

변경시 장점

  • 각 모듈별로 필요한 의존성들을 따로 관리 ⇒ 최소 의존성 보유

    ex) chat - rabbitMQ, MongoDB, Redis, websocket 등

    account - keycloak, spring-security, jwt 등

    study - ffmpeg, webclient 등

  • 어플리케이션은 필요한 모듈만 선택

    • ⭐️ 현재 혼자연습, 스터디 영상 저장을 비동기로 처리할 것을 계획 중인데 이 때 webclient 라는 비동기 client 사용하기 위해서는 WebFlux 의존성('spring-boot-starter-webflux') 필요함

      → 현재 사용하고 있는 Spring MVC ('spring-boot-starter-web')와 WebFlux 의존성을 함께 사용할 수 없음

      → 모듈별로 분리함으로써 스터디 관련 모듈에만 WebFlux 의존성 사용할 수 있음

  • 모듈 별 재사용, 공유 가능

  • 변경으로 인한 영향 최소화

모듈 분리

참고 : 우아한 테크 세미나, 우아한 형제들 - 멀티 모듈 설계 이야기

= 계층 분리 (역할과 책임에 따라)

스크린샷 2021-06-06 오후 9 59 22

스크린샷 2021-06-07 오전 12 12 35

우아한 형제들에서 사용했던 방식을 참고하되, 우리의 서비스에 맞게 구성

공통 모듈 계층 :

= 하나의 프로젝트의 모든 모듈에서 사용될 수 있는 것

  • witherview-core

    • 공통 business exception
    • util

이 때 외부 의존 관계 없이 java class만 정의

도메인 모듈 계층 :

= 하나의 모듈은 하나의 인프라스트럭쳐만 책임지도록 한다.

스크린샷 2021-06-06 오후 9 53 22

  • domain-mysql

    • entity

    • repository

      dependency:

      • spring-boot-starter-data-jpa

      • mysql:mysql-connector-java

  • domain-mongo (사실 이부분은 chat에서만 사용하는거니까 chat-api 내부에 정의해도 되..나? (일단 참고용 예시))

    • entity

    • repository

      dependency:

      • spring-boot-starter-data-mongodb

내부 모듈 계층 :

= 저장소, 도메인 외 시스템에서 필요한 모듈

= 어플리케이션, 도메인 비지니스를 모른다.

  • 이메일 검증 모듈

어플리케이션 모듈 계층 :

= 독립적으로 실행 가능한 어플리케이션 모듈 계층

= 하위 설계 했던 모듈들을 조립하여 서비스 비즈니스를 완성시킨다.

application

  • account-api (계정)

  • chat-api (채팅)

  • study-api (면접 연습 - 혼자, 스터디)

주저리주저리

  • 이 것이 최선일지는 모르겠다.

  • 그저 나의 커다란 욕심일지도

  • 현재 프로젝트에서 도메인 별로 디렉토리를 나눠서 관리하고 있기 때문에 분리작업에 대한 공수가 어어엄청 클 것 같진 않다 ?
    (막상 해보면 또 다를 수 있겠지만 = 그저 나의 욕심)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions