본문 바로가기
개발/MSA

[MSA] 모놀리식 어플리케이션 분해 전략(서비스 분리)

by 궁즉변 변즉통 통즉구 2024. 8. 17.
반응형

모놀리식 어플리케이션을 분해하는 전략을 알아본다. 아래 내용들은 도서 '소프트웨어 아키텍처 The Hard Parts'를 참조했다. 

 

아래 그림은 모놀리식 분해 전략을 위한 의사 결정 트리이다.

어플리케이션 분해전략 의사결정 트리, 출처: 소프트웨어 아키텍처 The Hard Parts

 

먼저 어플리케이션이 모듈화할 명분이 있는가?를 식별한다. 다시 말해 유지보수성, 테스트성, 배포성, 민첩성, 유연성 등을 필요로 하는 모놀리식 어플리케이션인지를 판단한다. 모놀리식 어플케이션 분해(모듈화)의 필요성에 대한 자세한 내용은 아래 링크를 참조한다.

https://happy-jjang-a.tistory.com/323

 

다음으로 분해가 가능한 코드인지를 평가한다. 코드 내부 구조가 적절한지 판별하는 절대적인 기준은 없으나, 코드의 특성을 거시적으로 살펴보는 방법들을 활용하면 내부 구조(특히, 컴포넌트/패키지 간 커플링)를 파악하는데 도움이 된다. 만약, 어플리케이션의 구조적인 조정이 절실하다고 판단되면, 일단 내부 구조부터 개선을 하고 분해 마이그레이션 작업을 수행하는 것이 좋다. 코드의 특성을 살펴보는 방법에는 아래 방법들이 있다. 

1. 구심/원심 커플링 평가

  • 구심 커플링(CA, Afferent Couplings): 컴포넌트, 클래스, 함수 등의 코드 아티팩트로 들어오는 접속 수
  • 원심 커플링(CE, Efferent Couplings): 다른 코드 아티팩트로 나가는 접속 수
  • 전체 커플링(CT): 구심 커플링(CA) + 원심 커플링(CE)
  • CA가 높을수록 해당 항목을 변경하기가 어렵고 비용이 많이 듬
  • 공유 자원이 얼마나 다른 파트에서 사용중인지? 패키지 단위(컴포넌트) 간의 결합도는 어떻게 되는지? 등 분석하는 툴(ex. JDepend, IntelliJ DSM 등)
    아래는 IntelliJ DSM 분석할 수 있는 메뉴이다. DSM 외에 다른 의존성 분석 메뉴들도 많아서 주기적으로 활용하면서 개발을 하면 된다.

IntelliJ DSM 메뉴와 분석 결과 샘플

2. 추상도 평가

  • 추상 아티팩트(인터페이스, 추상 클래스)와 구상 아티팩트(구현부)의 비율
  • 추상도(A) = 추상 아티팩트 합 / (구상 아티팩트 합 + 추상 아티팩트 합)

3. 불안정도 평가

  • 원심 커플링과 (구심 커플링 + 원심 커플링)의 비율
  • 어떤 컴포너트를 변경하면 그에 딸린 다른 컴포넌트를 얼마나 많이 변경해야 하는지 평가
  • 불안정도(I) = 원심 커플링(CE) / (구심 커플링(CA) + 원심 커플링(CE))
  • 모든 컴포넌트가 자기 완비형일 경우 안정도는 올라가지만 코드 중복은 불가피해짐

4. 메인 시퀀스로부터의 거리 평가 

  • 추상도와 불안정도 사이의 이상적인 관계를 나타냄
  • 메인 시퀀스로부터의 거리(D) = | A + I - 1 |
  • 메인 시퀀스 선에 가까울수록 컴포넌트 균형이 잘 맞는다는 의미[아래 그림 왼쪽]
  • 메인 시퀀스에서 오른쪽 위로 치우친 부분은 쓸모없는 구역(추상화가 과도하여 사용하기 어려운 코드)이고, 
    왼쪽 아래로 치우친 부분은 고통스러운 구역(추상화를 거의 안하고 구현코드만 있는 관리하기 힘든 코드)을 나타냄[아래 그림 오른쪽]

출처: 소프트웨어 아키텍처 The Hard Parts

 

 

모놀리식 어플리케이션 분해 전략

모놀리식 어플리케이션 분해 전략은 크게 2가지가 있는데 각각 어플리케이션 상황에 맞는 방법을 선택해서 적용한다. 

 

(1) 컴포넌트 기반 분해 전략

  • 어플리케이션의 논리적 구성요소인 컴포넌트(패키지단위 or 네임스페이스)를 정제/추출한 후 분산 아키텍처를 점진적으로 제어 가능한 방향으로 리팩토링 하는 패턴
  • 내부 컴포넌트 간의 경계가 명료하게 정의된 경우 적합

 

1. 컴포넌트 식별 및 사이징 

  • 컴포넌트를 식별하고 적절한 비중으로 분해를 진행
  • 아래 그림 예시에서는 '리포팅' 부분이 과도한 비중을 차지하고 있어서 이런 컴포넌트들을 적절히 분해를 해준다.

 

2. 공통 도메인 컴포넌트 수집 및 통합

  • 어플리케이션 비즈니스 처리 로직의 일부로 몇몇 컴포넌트에서 공통으로 사용되는 컴포넌트
  • 공통 도메인 기능을 통합하면 시스템 분해 시 중복 서비스 쉽게 제거 가능
  • 컴포넌트의 이름 등의 유사성을 바탕으로 공통 도메인 기능 식별 가능
  • 예시) 알림기능: ss.ticket.notification,  ss.billing.notification,   ss.survey.notification
             ⇒ ss.notification으로 통합

3. 컴포넌트 눌러 펴기 

  • 컴포넌트 파일들을 네임스페이나 패키지 구조의 마지막 노드(리프 노드)에만 정의해서 컴포넌트 구조를 조정
  • 아래 그림 왼쪽처럼 여러 곳에 산발되어 있는 컴포넌트 파일들을 오른쪽 그림처럼 마지막 리프 노드에만 정의되도록 조정 한다.

Before(왼쪽) => After(오른쪽)

4. 컴포넌트 의존성 결정

  • 1차적으로 정리한 컴포넌트 간의 의존성을 분석하여 어플리케이션 분해가 가능한지, 전체적으로 다시 재작성해야 하는지 식별
  • 컴포넌트 결합도 파악 후 컴포넌트 자체를 분해하면 해당 컴포넌트의 결합도를 줄일수도 있다

의존성을 식별하고(왼쪽), 의존성이 높은 컴포넌트는 공유Library화를 통해 의존성을 제거할 수 있다(오른쪽)

  • 아래와 같이 컴포넌트 간 결합도가 너무 높은 경우 사실상 분해가 어렵고, 전체적으로 재작성이 효율적이다.

컴포넌트간 결합도가 너무 높은 경우

5. 컴포넌트 도메인 생성

  • 어플리케이션 분해 시 세분화된 도메인 서비스 생성을 위해 컴포넌트를 논리적으로 그룹핑하는 것
  • 연관된 기능을 하는 컴포넌트들을 하나의 그룹으로 묶어준다.

고객과 분리되어 있던 과금결제, 과금이력, 지원계약 컴포넌트들을(왼쪽) customer 컴포넌트 하나로 그룹핑 함(오른쪽)

6. 도메인 서비스 생성 

  • 잘 정의 컴포넌트 도메인을 개별 배포가 가능한 서비스로 추출해서 서비스로 구성하는 것
  • 서비스 분리 후에는 수정작업의 공수가 많이 들 수 있어서 모든 컴포넌트 도메인을 식별하고 리팩터링을 마치기 전에는 적용하지 않는 것이 좋다

 

 

 

(2) 전술적 분기 전략

  • 전술적 분기 전략은 컴포넌트 기반 분해 전략보다 간단
  • 기존 어플리케이션의 사본을 만들고 필요없는 부분을 하나씩 제거해가는 패턴
  • 일정한 체계없이 코드가 뭉쳐있는 경우(진흙 잡탕)에 적합

장점 단점
 사전 분석작업 없이 즉시 작업 시작 가능  모놀리식 코드 상당부분이 남아 있을 가능성이 큼 
 코드 추출보다 삭제가 더 쉬움  크기만 줄었을 뿐 서비스 내부 코드가 이전 모놀리식과 비슷해짐
   기존코드에서 공통코드 및 공통 컴포넌트 식별이 어렵고 코드 일관성 유지 어려움

 

관련글:

 

[MSA] 서비스 분리 해야할 때와 통합 해야할 때(서비스 분해와 통합 요인)

MSA에서 서비스 분리를 고려할 때 어떤 경우에 서비스를 분리해야하고 반대로 어떤 경우에 서비스를 통합해야하는지 서비스의 분해인과 통합인에 대해서 알아본다. 간단하게 모률화, 세분도라

happy-jjang-a.tistory.com

 

반응형

댓글