GOF의 객체 패턴을 확대하면 아키텍쳐도 몇가지의 패턴을 가진다는 걸 알수 있다.

가장 대표적으로 Layer 패턴을 들 수 있는데 시스템의 규모가 커서 분해(decomposition) 할 필요가 있고 하위 레벨과 상위 레벨의 이슈가 서로 혼재해 있을때 나온다. 앞글의 실험실과 비실험실은 결국 레이어 패턴과 비슷하지만 굳이 실험실과 비실험실이라고 부른 것은 기계적인 효율성이 필요한 곳과 아닌곳을 구분하려고 실험실이라는 용어를 사용하였다. 레이어 패턴의 대표적인 예는 많이 알려진 OSI 7 Layer가 있고 Java의 VM자체가 하나의 Layer이다.

레이어 패턴은 아래와 같은 특징이 있다.

1. 나중에 소스 코드가 변경하다고 하더라도 그것이 시스템 전체에 파문을 일으켜서는 안된다. 그런 변경이 있더라도 오직 하나의 컴포넌트 내에만 국한되어야 하며 다른 컴포넌트에는 영향을 미쳐선 안된다.

2. 인터페이스는 안정성(stability)을 갖추어야 하며, 표준 구현부에 미리 지정되어 있는 것이 좋다.

3. 시스템의 각 부분들은 교환가능해야 한다. 일반적으로 변경에 대비해 설계하면, 시스템을 발전시키도록 촉진할 수 있다.

4. 현재 설계하고 있는 시스템과 동일한 하위 레별의 이슈 때문에 추후에 다른 시스템을 구축해야 할 필요가 있을지 모른다.

5. 각 컴포넌트는 이슈 하나만을 담당하도록 구현되어야 한다. 만약 한 컴포넌트가 다른 이슈를 구현하면 일관성을 잃게 된다.

6. 컴포넌트 경계를 넘나드는 처리가 발생할수록 성능을 하락시킬 가능성이 커진다.


"전산학의 모든 문제는 또 다른 수준의 간접층으로 해결할 수 있다."
라는 유명한 말을 통해 레이어의 개념을 알린 이는 램슨이라고 알려져 있는데 램슨은 사실 서브루틴의 개념을 만든 휠러에게서 따왔다고 밝힌바 있다. 휠러는 그 말에 이어서
 "그러나 그러면 또 다른 문제가 생기는 것이 일반적이다."
라며 간접과 계층화는 공간과 시간의 부담을 추가하고 코드의 가독성을 해칠수 있는 문제점도 같이 언급하였다.

보통의 경우에는 공간과 공간상의 추가 부담은 그리 크지 않기 때문에 일반적으로 큰 관심사가 되지 못한다. 대부분의 경우 추가적인 포인터 참조나 서브루틴 호출에 의한 시간 지연은 전반적인 구조 개선에 비할때 사소한 수준에 그친다. 사실 요즘의 현대적인 프로그래밍 언어들은 추가적인 유연성을 얻기 위한 목적으로 일부 연산들의 경우 항상 하나의 간접층을 거치도록 하는 경향을 보이고 있다. 예를 들어 java나 C#의 경우 객체에 대한 모든 접근이 하나의 포인터 간접을 거치게 하는데, 이는 쓰레기 수거를 위한 것이다. 또한 Java에서는 인스턴스 메서드에 대한 거의 모든 호출이 하나의 조회 테이블을 통해서 분배되는데, 이는 다른 클래스를 상속하는 클래스들이 실행시점에서 메서드를 재 정의 할 수 있도록 하기 위한 것이다.

모든 객체 접근과 메서드 호출에 부가되는 이러한 추가부담에도 불구하고 두 플랫폼은 시장에 선전을 펼치고 있다. 어떤 경우에서는 개발자가 코드에 집어넣은 간접을 컴파일러가 최적화를 통해서 제거하기도 한다. 대부분의 컴파일러들은 함수를 호출하는 것이 함수의 코드를 호출지점에 직접 삽입하는 것(소위 인라인 함수_보다 비싼 경우 자동적으로 그러한 인라인 처리를 수행한다.

반면 코드의 가독성에 대한 간접의 영향은 아주 중요한 문제이다. 지난 50년간 CPU의 속도는 엄청나게 빨라진 반면 코드를 이해하는 사람의 능력은 별로 발전하지 않았다는 점을 감안한다면 충분히 이해할 수 잇을 것이다. 그래서 애자일 프로세스 옹호자들은 오늘이 구체적인 요구가 아니라 미래에 생길 수도 있는 애매하고 명시되지 않는 요구사항들을 처리하기 위해 계층들을 도입할 때에는 아주 신중해야 한다고 조언한다. 스몰더스는 이에 대해 성능 안티패턴을 논의하면서 계층은 케이크를 위한 것이지 소프트웨어를 위한것이 아니다 라고 비꼰 바 있다.


레이어 패턴은 다은과 같은 단계를 거친다.

# 테스크를 레이러로 묶는 추상기준을 정의해야 한다. 이 추상기준을 플랫폼으로부터 개념적 거리(conceptual distance)로 삼는 경우가 많은데 실제 소프트웨어 개발에서는 하드웨어로부터의 거리와 개념적 복잡성의 추상적 기준을 혼합하여 사용한다.

1. 사용자를 위한 시각적 요소
2. 특수하게 지정된 애플리케이션 모듈
3. 공통 서비스 레벨
4. 운영체제 인터페이스 레별
5. 운영체제
6. 하드웨어

# 추상 기준에 따라 얼마나 많은 추상 레별로 나눌지를 결정하고 레이어마다 역할을 부여하고 테스크를 할당한다. ( 상당한 경험과 통찰력이 필요하다.)

# 서비스를 상세히 정의한다.
  레이어 패턴을 구현할때 가장 중요한 원칙은 레이어들을 서로 엄밀히 구분해야 한다는 점이다.  기반레이어는 가볍게 유지하는 대신 상위 레이어는 광범위한 적용석을 확보하도록 확장하는 것이 좋다. 이런 현상을 재사용의 역 피라미드 구조라고 한다.

# 레이어에 대한 정의를 개선해 간다.

# 각 레이어마다 인터페이스 하나씩을 정의한다.

# 개별 레이어를 구조화한다.

# 인접한 레이어들 간의 통신 방식을 정의한다.

# 인접한 레이어들을 서로 분리시키고 오류 핸들링 전략을 설계한다.

레이어 패턴을 사용하지만 부분적으로 터널을 사용하는 경우가 있는 일종의 변형코드를 사용하는 완화된 레이어 시스템을 사용하기도 하는데 유지보수성을 포기하는 대가로 유연성과 성능을 확보하게 된다. 어플리케이션보다 인프라 시스템에서 종종 이런 편법을 찾아볼수 있다. 이러한 편법이 종종 허용되는 이유는 인프라 시스템이 어플리케이션 시스템보다 변경이 빈번하지 않으며 대체로 성능을 유지보수성보다 중요하게 여기기 때문이다. 그리고 앞서 소개한 DB Framework에도 일종의 터널링이 존재하지만 일종의 예외이기 때문에 주의해서 사용해야 한다.


레이어 패턴은 아래와 같은 장단점이 있다.

장점
1. 레이어를 재사용할 수 있다.
2. 표준을 지원한다.
3. 종속성을 국지적으로 최소화한다.
4. 교환가능성이 확보된다.


단점
1. 동작이 변경될 경우 단계별로 재작업이 필요하다.
2. 효율이 낮다.
3. 불필요한 작업이 수행될 수 있다.
4. 레이어의 적절한 개수나 규모를 결정하는 것이 어렵다.



 

'Framework > 아키텍쳐 일반' 카테고리의 다른 글

아키텍쳐 패턴 - Broker 패턴  (0) 2009.03.12
아키텍쳐 패턴 - Pipes and Filter 패턴  (0) 2009.03.11
Class Design  (0) 2009.03.07
나쁜 디자인의 징후  (0) 2009.02.22
Design Principle - SRP  (0) 2009.02.22
Posted by bleujin