개발자에서 아키텍트로 - 7. 패턴으로 기초 만들기1(아키텍처 패턴)
노련한 아키텍트는 새로운 문제를 접할 때 사진의 설계 패턴 목록을 뒤적이며 유사한 해법을 찾은 후에야 새로운 설계를 시작합니다. 적당한 패턴을 찾을 때는 문제의 특이사항 몇 가지를 채워 넣은 후에 요구사항에 맞게 조금 수정합니다.
7.1 아키텍처 패턴이란 무엇인가?
아키텍처 패턴이란 특정 문제에 대해 재사용할 수 있는 해법입니다. 소프트웨어 아키텍처 패턴은 알려진 몇 가지 구조의 조합으로 품질 속성을 끌어올리는 방법입니다. 문제에 적합한 패턴을 선택하면 함정을 피할 수도 있고 바닥부터 디자인하는 수고를 덜 수도 있습니다. 그 외에도 패턴의 장점이 더 있습니다. 잘 알려진 패턴을 사용하면 대화하고 설득하기에 용이합니다. 그림 한 장이 백 마디 말보다 낫습니다. 패턴은 수천 장의 그림과 같은 효과가 있습니다. 유명한 패턴은 프레임 워크나 플랫폼으로도 존재하므로 적용하기 편합니다.
7.2 레이어layer pattern 패턴
레이어 패턴은 가장 흔히 사용되고 필요 이상으로 남용되는 패턴입니다. 코드를 나누고 관심사별로 독립적인 레이어를 구분하면 개발자들이 함께 일하기가 수월해집니다. 레이어 간의 결합은 낮추고 응집을 높이면 유지 보수성이 좋아집니다. 레이어 패턴을 사용하면 하나의 모듈을 업데이트할 때 다른 모듈이 받는 영향을 최소화할 수 있습니다.
카테고리 | 모듈 |
구성요소 | 레이어 : 기능적으로 응집할 수 있는 단위 |
관계 | 사용할 수 있음 : 하나의 모듈을 다른 레이어에서 사용할 수 있음을 나타낸다. |
사용 규칙 | 어떤 모듈이든 반드시 하나의 레이어에만 존재해야 한다. 상위 레이어는 하위 레이어를 사용할 수 있으며, 이를 '사용할 수 있음' 관계로 맺는다. 이 관계는 한 방향으로만 흘러야 한다. 또한 현재 레이어가 바로 하위 레이어만 사용할 수 있도록 제한을 둘 수 있다. 순환 참조는 허용하지 않는다. |
강점 | 유지 보수성, 독립 구동 가능성, 재사용성, 테스트 가능성, 설계 시점의 유연성이 높아진다. 이론적으로 구현이 단순하며, 레이어 단위로 구현하기 좋다. |
약점 | 최상위 레이어와 최하위 레이어 간에는 별도의 추상화 작업이 필요하다. 이 추상화 작업 때무에 복잡도가 올라가거나 성능이 저하될 수 있다. 너무 많은 레어는 구현하기 어려우며, 추상화에서 어딘가 비어 있으면 개발자가 괴로워 진다. |
7.3 포트와 어댑터port and adapter pattern 패턴
포트와 어댑터 패턴은 핵심 비즈니스 로직을 격리할 때 유용 합니다. 다양한 주제에 적용할 수 있을뿐더러 데이터와 이벤트를 격리된 환경에서 테스트할 때도 사용할 수 있습니다. 실행 중에도 마치 플러그를 꽂듯이 어댑터를 구현하면, 특정 입력 소스를 비즈니스 로직에 주비해 데이터와 이벤트를 제공할 수 있습니다. 어댑터는 소프트웨어 구축 시 또는 실행 시에 환결설정 값에 따라 바뀔 수 있습니다. 그러므로 이 패턴은 여러 입력 장치를 지원하는 소프트웨어나 입력 환경이 바뀔 수 있는 경우에 적용하면 좋습니다.
카테고리 | - 모듈, 컴포넌트와 커넥터 |
구성 요소 | - 레이어 : 데이터나 이벤트로 어떤 값이 올지 모르는 도메인 또는 비즈니스 로직 - 포트 : 레이어와 어댑터 사이의 인터페이스를 정의. 포트는 레이어 간의 관계를 어댑터로 분리 할 수 있게 한다. - 어댑터 : 레이어가 데이터 또는 이벤트에 액세스하는 데 사용하는 코드. 외부 데이터 소스, 장치 또는 기타 구성 요소와 상호작용 한다. |
관계 | - 노출 : 특정 레이어에서 가능한 포트를 표시 - 구현 : 어댑터를 제한하는 포트를 표시 - 주입 : 레이어에서 사용 가능한 어댑터를 표시 |
사용 규칙 | - 레이어는 포트를 노출한다. 모든 레이어가 포트를 노출할 필요는 없으며, 포트를 노출하지 않는 레이어는 내부 레이어(inner layer)라고 한다. - 어댑터는 하나 이상의 포트에 적용할 수 있도록 포트의 제약 조건을 충족해야 한다. - 어댑터가 포트를 적용할 수 있도록 인터페이스를 구현한 경우, 어댑처는 포트로만 정보를 주입해야 한다. - 요소와 관계를 구현하는 기술에 따라 다르지만, 이 패턴은 대체로 설계 시점 또는 실행 시점에 참고하기에 유용하다. 설계할 때 모델을 모듈 구조로 표현할지 컴퓨넌트와 커넥터 구조로 표현할지 일관성이 있어야 한다. |
강점 | - 테스트 가능성, 유지 보수성, 그리고 변경에 대한 적응력을 높인다. 레이어와 어댑터마다 서로 다른 팀이 함께 일할 수 있다. |
약점 | - 소프트웨어 실행 중에도 어댑터를 선택할 수 있는 메커니즘을 구현해야 한다. 보안이나 안정성 등 소프트웨어 품질이 어댑터에 따라 달라질수 있다. 그러므로 서트 파트 어댑터느 주의해서 적용해야 한다. |
7.4 파이프 앤 필터pipe and filter pattern 패턴
파이트 앤 필터 패턴에서 요소 하나하나는 필터라고 부르며 단방향으로 데이터를 변형하는 작업만 합니다. 데이터는 필터에서 필터로 빠르게 흐르고, 병렬적으로 데이터 처리가 이루어지기도 합니다. 필터 간의 관계를 느슨하게 만들수록 필터를 재사용하기 용이하고 새로운 파이프라인을 만들 때 다양한 구성으로 결합할 수 있습니다.
이 패턴은 데이터 분석과 처리에서 자주 사용됩니다. 유닉스 명령어 pipe를 사용해 봤다면 이미 이 패턴을 맛본 셈입니다.
파이프와 필터 패턴과 비슷한 패턴으로 배치 시퀀셜 패턴이 있는데, 한가지 큰 차이점이 있습니다. 배치 시퀀셜 패턴은 단계별로 하나의 작업만 실행하지만 파이프와 필터 패턴은 병렬 처리가 가능합니다. 게다가 배치 시퀀셜 패턴은 주요 단계마다 모든 데이터를 디스크에 저장한 후 다음 단계로 넘어가지만, 파이프와 필터 패턴은 스트리밍 데이터를 가정합니다.
카테고리 | - 컴포넌트와 커넥터 |
구성 요소 | - 필터 : 데이터를 읽고 변형한 후, 결과 데이터를 보내는 컴포넌트. 통상적으로 필터는 데이터를 읽자마자 처리하도록 구현한다. 필터마다 기대하는 입력과 출력을 정의한다. - 파이프 : 필터에서 필터로 전달하는 커넥터. 데이터의 순서를 유지한다. 파이프는 단일 입력과 출력을 하며, 전달 과정에서 데이터를 변경하지 않는다. - 변종 패턴으로 소스와 싱크를 포함하는 경우가 있다. 소스는 데이터만 생산만 하고, 싱크는 데이터를 받기만 한다. |
관계 | - 부착물 : 한 필터의 출력과 다른 필터의 입력을 파이프로 연결한다. |
사용 규칙 | - 입력과 출력이 호환되는 필터끼리만 파이프로 이을 수 있다. 필터 하나는 다른 필터에 의존하지 않고 온전히 독립적이어야 하며, 다른 필터로부터의 데이터 흐름을 전혀 모르는 상태로 동작해야 한다. |
강점 | - 성능, 재사용성, 변경 대응력이 높음 |
약점 | - 파이트와 필터 시스템은 인터랙티브하지 않으며, 패턴 자체로는 사용자 인터페이스를 갖기 어렵다. 안정성을 높이는 패턴은 아니지만 필터 하나마다 에러처리를 하도록 설계하면 안정성을 높일 수는 있다. 이 패턴은 쉽게 생각하고 구성할 경우, 여러 개의 필터가 동시에 실행되면서 전체 시스템 성능이 크게 하락하거나 각종 프로세싱 비용이 높아지는 문제를 겪을 수 있다. |