메모

  • 시스템의 규모가 작을 때에는 이 패턴의 도입을 신중히 결정할 것.
  • 동작이 변경되면 레이어별로 수정 작업이 필요할 수 있어, 작은 규모의 시스템에서는 불필요한 작업이 증가할 수 있다.
  • 이 패턴은 적절한 레이어의 수를 산출하는 것부터가 문제.
    • 레이어의 수가 너무 작다면 이 패턴의 장점을 살리기 어렵다.
    • 레이어의 수가 너무 많다면 복잡도와 시스템 오버헤드가 증가하고, 중복 작업이 늘어날 수도 있다.
  • 경험상 레이어를 없애는 쪽의 리팩토링이 효과가 좋은 경우가 많았다.

From: 패턴 지향 소프트웨어 아키텍처 1

정황(context)

시스템의 규모가 커서 분해(decomposition)할 필요가 있다. 1

사례: OSI 7계층 모델

레이어 형태로 이루어진 아키텍처 중 가장 잘 알려진 예제는 아마도 네트워크 프로토콜(networking protocol)일 것이다. 네트워크 프로토콜은 컴퓨터 프로그램들이 머신들 간의 경계를 넘나들며 통신하는 방법에 대한 규칙들로 이루어져 있다. 포맷(format), 내용(content), 그리고 모든 메시지의 의미(meaning) 등이 미리 명확하게 정의되어 있으며, 모든 시나리오 역시 대체로 주어진 시퀀스 차트에 따라 상세히 정의되어 있다. 이런 네트워크 프로토콜의 경우, 비트 전송(bit transmission)에서부터 상위 레벨 애플리케이션 로직(high-level application logic)에 이르기까지, 다양한 추상 레벨에 해당하는 규약(agreement)을 엄밀히 준수한다. 그 덕분에 설계자는 몇 개의 서브프로토콜을 선택하고 그것들을 레이어들로 정돈해 설계할 수 있다. ISO(international standardization organization)에서는 다음과 같은 아키텍처 모델을 'OSI 7계층 모델(open systems interconnection 7-layer model)' [Pan921]로 정의하고 있다.

(후략) 2

사례: 가상 머신

가상 머신(VM, virtual machine) - 하위 레벨(low-level)의 다양한 운영체제나 하드웨어로부터 상위 레벨을 격리시키는 가상 머신이 하위 레벨 역할을 한다고 볼 수 있다. 예를 들어 자바 가상 머신(JVM, Java virtual machine)은 바이너리 코드 포맷을 정의하고 있다. 자바 프로그래밍 언어로 작성된 코드는 바이트코드(bytecode)라는 플랫폼에 중립적인 바이너리 코드(platform-neutral binary code)로 변환되며 이것을 해석(interpretation)하기 위해 JVM 으로 전달된다. JVM 자체는 특정 플랫폼에 종속되어 있다. 다시 말해 JVM 은 서로 다른 운영체제와 프로세서에 적합하도록 각기 따로 구현되어 있다. 두 단계로 변환 처리하는 방식을 채택함으로써 플랫폼에 중립적인 소스 코드가 가능했고, 바이너리 코드를 도입함으로써 플랫폼 독립성을 유지하는 대신 사람이 해독할 수 없다. 3

사례: 윈도우 NT

윈도우 NT - 이 운영체제(operating system)는 Microkernel 패턴(183)을 적용해 구조화되어 있다. NT 실행(executive) 컴포넌트는 Microkernel 패턴의 마이크로커널 컴포넌트에 해당한다. NT 실행 컴포넌트는 '변형' 절에서 설명한 완화된 레이어 시스템'에 해당한다. NT 실행 컴포넌트는 다음과 같은 레이어로 구성된다.

  • 시스템 서비스 - 서브시스템과 NT 실행 컴포넌트 간의 인터페이스 레이어
  • 리소스관리(resource management) 레이어 - 이 레이어는 객체 관리자(object manager), 보안 참조 모니터(security reference monitor), 프로세스 관리자(process manager), I/O 관리자(I/O manager), 가상 메모리 관리자(virtual memory manager), 로컬 프로시저 호출(local procedure call) 등의 모듈로 구성된다.
  • 커널 - 이 레이어는 인터럽트 핸들링(interrupt handling), 예외 핸들링(exception handling), 멀티프로세서 동기화(multiprocessor synchronization), 스레드 스케줄링(thread scheduling), 스레드 디스패치(thread dispatching) 등의 기본 기능을 관할한다.
  • HAL(hardware abstraction layer) - 이 레이어는 각기 다른 프로세서 계열에 있는 머신들 간에 하드웨어의 차이를 숨긴다.
  • 하드웨어 - 커널과 I/O 관리자가 효율이라는 이유로 기반 하드웨어에 액세스하기 때문에 윈도우 NT 에서는 Layers 패턴의 원칙을 완화하여 적용한다.

From: 도메인 주도 설계

에릭 에반스는 다음과 같이 계층화의 장점을 이야기한다.

계층화의 가치는 각 계층에서 컴퓨터 프로그램의 특정 측면만을 전문적으로 다룬다는 데 있다. 이러한 전문화를 토대로 각 측면에서는 더욱 응집력 있는 설계가 가능해지며, 이로써 설계를 훨씬 더 쉽게 이해할 수 있다. 물론 가장 중요한 응집력 있는 설계 측면을 격리하는 계층을 선택하는 것도 매우 중요하다. 4

이러한 계층화는 관례적으로 받아들여지고 있는 유명한 구조가 이미 존재한다.

거듭 말하지만 경험과 관례를 바탕으로 널리 받아들여지는 계층화가 어느 정도 정해졌다. 이러한 계층화는 다양한 모습으로 나타나지만 대다수의 성공적인 아키텍처에서는 아래의 네 가지 개념적 계층으로 나뉜다.

  • td
    • 사용자 인터페이스 (또는 표현 계층)
    • 사용자에게 정보를 보여주고 사용자의 명령을 해석하는 일을 책임진다. 간혹 사람이 아닌 다른 컴퓨터 시스템이 외부 행위자가 되기도 한다.
  • td
    • 응용 계층
    • 소프트웨어가 수행할 작업을 정의하고 표현력 있는 도메인 객체가 문제를 해결하게 한다. 이 계층에서 책임지는 작업은 업무상 중요하거나 다른 시스템의 응용 계층과 상호작용하는 데 필요한 것들이다.
      이 계층은 얇게 유지된다. 여기에는 업무 규칙이나 지식이 포함되지 않으며, 오직 작업을 조정하고 아래에 위치한 계층에 포함된 도메인 객체의 협력자에게 작업을 위임 한다. 응용 계층에서는 업무 상황을 반영하는 상태가 없지만 사용자나 프로그램의 작업에 대한 진행상황을 반영하는 상태를 가질 수는 있다.
  • td
    • 도메인 계층 (또는 모델 계층)
    • 업무 개념과 업무 상황에 관한 정보, 업무 규칙을 표현하는 일을 책임진다. 이 계층에 서는 업무 상황을 반영하는 상태를 제어하고 사용하며, 그와 같은 상태 저장과 관련 된 기술적인 세부사항은 인프라스트럭처에 위임한다. 이 계층은 업무용 소프트웨어의 핵심이다.
  • td
    • 인프라스트럭처 계층
    • 상위 계층을 지원하는 일반화된 기술적 기능을 제공한다. 이러한 기능에는 애플리케 이션에 대한 메시지 전송, 도메인 영속화, UI에 위젯을 그리는 것 등이 있다. 또한 인프라스트럭처 계층은 아키텍처 프레임워크를 통해 네 가지 계층에 대한 상호작용 패턴을 지원할 수도 있다.

어떤 프로젝트에서는 사용자 인터페이스와 애플리케이션 계층을 명확히 구분하지 않기도 하며, 여러 개의 인프라스트럭처 계층이 존재하는 프로젝트도 있다. 하지만 MODEL-DRIVEN DESIGN을 가능케 하는 것은 결정적으로 도메인 계층을 분리하는 데 있다.

그러므로

복잡한 프로그램을 여러 개의 계층으로 나눠라. 응집력 있고 오직 아래에 위치한 계층에만 의존하는 각 계층에서 설계를 발전시켜라. 표준 아키텍처 패턴에 따라 상위 계층과의 결합을 느슨하게 유지하라. 도메인 모델과 관련된 코드는 모두 한 계층에 모으고 사용자 인터페이스 코드나 애플리케이션 코드, 인프라스트럭처 코드와 격리하라. 도메인 객체(표현이나 저장, 애플리케이 션 작업을 관리하는 등의 책임에서 자유로운)는 도메인 모델을 표현하는 것에만 집중할 수 있다. 이로써 모델은 진화를 거듭해 본질적인 업무 지식을 포착해서 해당 업무 지식이 효과를 발휘할 수 있을 만큼 풍부하고 명확해질 것이다. 4

From: 소프트웨어 아키텍처 101

아키텍처 싱크홀 안티패턴

레이어드 아키텍처에서는 아키텍처 싱크홀architecture sinkhole 안티패턴을 조심해야 합니다. 요청이 한 레이어에서 다른 레이어로 이동할 때 각 레이어가 아무 비즈니스 로직도 처리하지 않고 그냥 통과시키는 안티패턴을 말합니다. 예를 들어, 유저가 기본 고객 데이터(예: 이름, 주소)를 조회하는 단순 요청을 하면 프레젠테이션 레이어가 응답하는 아키텍처가 있다고 합시다. 프레젠테이션 레이어는 비즈니스 레이어에 요청을 전달하고, 비즈니스 레이어는 아무 일도 하지 않고 규칙 레이어로 넘기고, 규칙 레이어 역시 아무 일도 안 하고 다시 퍼시스턴스 레이어에 넘기고… 결국, 퍼시스턴스 레이어가 데이터베이스 레이어에 단순 조회 SQL을 실행하여 고객 데이터를 가져오면 취합, 계산, 규칙 적용, 데이터 변환 등 일체의 로직 없이 다시 왔던 길을 거꾸로 돌아갑니다. 이런 흐름은 불필요한 객체 초기화 및 처리를 빈번하게 유발하고 쓸데없이 메모리를 소모하며 성능에도 부정적인 영향을 끼칩니다.

아키텍처 싱크홀 안티패턴에 해당하는 시나리오가 전무한 레이어드 아키텍처는 아마 하나도 없을 것입니다. 그러므로 이 안티패턴으로 처리 중인 요청의 전체 비율을 따져보는 것이 중요합니다. 80대 20 법칙을 적용해서 전체 요청의 20%가 싱크홀인 정도면 그런대로 괜찮은 수준입니다. 그러나 분석 결과 80%가 싱크홀이라면 이 문제 도메인에 레이어드 아키텍처는 적합한 아키텍처 스타일이 아니라는 증거입니다. 아키텍처 싱크홀 안티패턴을 해결하는 또 다른 방법은 아키텍처의 모든 레이어를 개방하는 것입니다. 그러나 이는 아키텍처상 변경 관리의 어려움이 가중되는 트레이드오프가 있음을 분명하게 인식해야 합니다. 5

참고문헌

  • 도메인 주도 설계 / 에릭 에반스 저 / 이대엽 역 / 위키북스 / 2011년 07월 21일 / 원제 : Domain-Driven Design
  • 소프트웨어 아키텍처 101 / 마크 리처즈, 닐 포드 저/이일웅 역 / 한빛미디어 / 초판 1쇄 발행 2021년 11월 01일 / 원제: Fundamentals of Software Architecture
  • 패턴 지향 소프트웨어 아키텍처 Volume 1 / Frank Buschmann 외 / 김지선 역 / 지앤선(志&嬋) / 발행 2008년 01월 18일

주석

  1. 패턴 지향 소프트웨어 아키텍처 Volume 1. 2장. 34쪽. 

  2. 패턴 지향 소프트웨어 아키텍처 Volume 1. 2장. 33쪽. 

  3. 패턴 지향 소프트웨어 아키텍처 Volume 1. 2장. 49쪽. 

  4. 도메인 주도 설계. 4장. 71쪽.  2

  5. 소프트웨어 아키텍처 101. 10장. 187쪽.