2026년 7월 4일 토요일

[Code] 모듈러 모놀리딕(Modular Monolithic) & Python 예제 #1

모듈러 모놀리딕과 파이썬 예제 #1

모률러 모놀리딕(Modular Monolithic) 아키텍처는 시스템을 하나의 단일 프로세스(Monolithic)로 배포하되, 내부 코드는 독립적인 모듈(Module)단위로 엄격하게 분리하여 결합도를 낮추는 아키텍처입니다. 각 모듈은 내부 구현을 숨기고(캡슐화), 명확한 인터페이스를 통해서만 소통해야 합니다.

기본예제 Project를 main.py | cli.py | feature_a.py | feature_b.py 로 구성하였고, 파이썬으로 언어입니다.

 - main.py 애플리케이션 진입
 - cli.py 사용자 인터페이스 입/출력 담당 모듈
 - feature_a.py 비지니스 로직 A 모듈
 - feature_b.py 비지니스 로직 B 모듈


1. 비지니스 로직 A 모듈 (feature_a.py)
 외부에는 데이터를 처리하는 핵심 인터페이스(run)만 노출하고, 내부 동작 알고리즘(_secret_process)은 숨김힙니다. 

# feature_a.py
def _secret_process(data: str) -> str:
    """모듈 내부에서만 사용하는 캡슐화된 메서드 (Private)"""
    return f"[A 모듈 가공] -> {data}"

def run(input_value: str) -> str:
    """외부에서 호출하는 명확한 Public API 인터페이스"""
    print("⚙️ A 기능 모듈 작동 중...")
    result = _secret_process(input_value)
    return f"A 기능 완료 결과: {result}"


2. 비지니스 로직 B 모듈 (feature_b.py)
 A 모듈과 완전히 독립되어 있으며, 자신만의 비즈니스 로직을 수행합니다. 

# feature_b.py
def run(input_value: str) -> str:
    """외부에서 호출하는 명확한 Public API 인터페이스"""
    print("⚙️ B 기능 모듈 작동 중...")
    # 간단한 비즈니스 로직 예시 (역순 정렬)
    reversed_data = input_value[::-1]
    return f"B 기능 완료 결과: {reversed_data}"


3. 입출력 담당 모듈 (cli.py)
 비지니스 로직(A, B)이 어떻게 돌아가는지 전혀 알 필요가 없습니다. 오직 사용자에게 입력을 받고 결과를 출력하는 UI역할에만 충실합니다. 

# cli.py
def get_user_choice() -> tuple[str, str]:
    """사용자로부터 메뉴 선택과 입력값을 받는 인터페이스"""
    print("\n==============================")
    print("1: A 기능 실행")
    print("2: B 기능 실행")
    print("q: 프로그램 종료")
    print("==============================")
    
    choice = input("원하는 기능을 선택하세요: ").strip()
    if choice == 'q':
        return choice, ""
        
    user_input = input("기능에 전달할 텍스트를 입력하세요: ")
    return choice, user_input

def display_result(result: str):
    """결과 화면을 출력하는 인터페이스"""
    print("\n📢 [CLI 출력]")
    print(f"결과: {result}")


4. 진입점 및 모듈 조립 (main.py)
 애플리케이션을 초기화하고, 각 모듈의 인터페이스를 연결하는 역할을 합니다. 중요한 점은 A모듈과 B모듈이 서로 참조하지 않고, CLI모듈도 A, B을 알지 못하며, 오직 main.py가 이들을 중재한다는 것입니다. 

# main.py
import cli
import feature_a
import feature_b

def bootstrap():
    """프로그램 초기 실행 및 준비 단계"""
    print("🚀 시스템 초기화 중... 모듈 로드 완료.")
    print("모듈러 모놀리딕 애플리케이션을 시작합니다.")

def main():
    bootstrap()
    
    while True:
        # 1. CLI 모듈을 통해 사용자 입력 수집
        choice, user_data = cli.get_user_choice()
        
        if choice == 'q':
            print("👋 프로그램을 종료합니다.")
            break
            
        # 2. 제어 흐름 분기 및 모듈 간 중재
        result = ""
        if choice == '1':
            # CLI에서 받은 데이터를 A 모듈 인터페이스로 전달
            result = feature_a.run(user_data)
        elif choice == '2':
            # CLI에서 받은 데이터를 B 모듈 인터페이스로 전달
            result = feature_b.run(user_data)
        else:
            result = "❌ 잘못된 선택입니다. 다시 시도하세요."
            
        # 3. 처리된 결과를 다시 CLI 모듈을 통해 출력
        cli.display_result(result)

if __name__ == "__main__":
    main()


모듈러 아키텍처 관점에서의 핵심 포인트
 - 낮은 결함도(Low Coupling) : feature_a.py와 feature_b.py는 서로의 존재를 모릅니다. 나중에 B기능을 삭제하거나, C기능으로 대체해도 A기능에 영향이 없습니다. 

 - 높은 응집도(High Cohesion) : cli.py는 입출력만 담당하고, feature_a는 본인의 데이터 처리에만 집중합니다. UI가 웹(Web)이나 GUI로 바뀌더라도 cli.py만 수정하거나 교체하면 됩니다. 

 - 단일 진입점(Single Entry Point) : main.py가 전체 흐름을 제어하는 컨트롤 타워 역할을 수행하여 모듈 간의 무분별한 직접 참조(Spaghetti Code)를 방지합니다. 




모듈러 모놀리딕 배포관점 및 개발/논리 관점 
 - 배포관점 : 전체 시스템이 하나의 거대한 '애플리케이션'으로 묶여 있으며, 단일 프로세스와 메모리 공간을 공유합니다. 배포관점은 모놀리딕 입니다. 

 - 개발/논리 - 아키텍처 관점 : 시스템 내부가 모듈별로 엄격하게 분리되어 있습니다. 각 모듈은 자신만의 내부 로직과 데이터 액세스 계층을 가지며, 외부에는 명확한 'Public API 인터페이스'만 노출하여 소통합니다. 

댓글 없음:

댓글 쓰기