개요

소프트웨어 아키텍처에 대해서 학습을 하다가 보면, 정말 많은 문서 작업을 요구한다. 정말 이런 것들이 다 필요한 것일까? 정말 다 줄이고 하나만 남긴다면 무엇을 할 수 있을까? 아니면 아예 문서 작업을 하지 않으려 한다면 그래도 이건 꼭 해보자면 무엇을 이야기할 수 있을까?

애자일 하게 개발을 진행하는 조직에서 요구 사항도 취합되어 백로그에 유저 스토리들이 쌓여 있다고 해보자. 이렇게 개발하다 보면, 자연 스럽게 개발자 수준에서 설계도 되어 우리 팀의 아키텍처가 내재되어 나오게 된다. 

하지만, 위의 상황은 상당히 이상적이다. 여러 담당자들이 구현을 해 가다 보면, 이상하다고 느껴지는 부분이 생기곤 한다. 진행이 안되고 막혀 있다는 부분이 있다. 이러한 부분은 의사 결정이 필요할 수도 있고, 실험을 통해서 확인이 필요할 수도 있다. 여기서는 의사 결정을 해야 하는 경우에 대해서 다뤄보자. 이를 위한 것이 아키텍처 의사 결정이고 이를 기록하는 것이 아키텍처 의사 결정 레코드 (Architectural Decision Record)이다.

이렇게 Architect는 의사 결정자나 이해관계자(Stakeholder)가 결정할 수 있또록 정보를 제공하여 결정을 지원하거나, 책임이 자신에게 있다면 기술적인 결정을 해야 한다. 그렇다면, 무엇을 가지고 어떻게 할 수 있을까?

아키텍처 의사 결정 기록 (ADR)소개

이와 같은 경우를 위해 활용할 수 있는 것이 다음과 같은 아키텍처 의사 결정 기록(Architectural Decision Record, ADR)이다. [1]에서는 ADR의 아주 간단한 형식을 보여 준다.

[기능 또는 컴포넌트]에 해당하는 맥락에서,
[요구 사항 또는 목표로 하는 품질 속성(Quality Attribute)]을 충족할 필요가 있다,
우리는 [이익]을 우선적으로 달성하기 위해
[선택된 옵션]을 채택하기로 결정하고
그리고 [대안]은 선택하지 않아서
그 선택에 따르는 [부정적인 결과]는 받아들인다.

이 내용은 아주 간단하게 기술되어 있다. 그렇기 때문에 다음과 같이 나누어 상세 한 부분을 살펴 볼 수 있다.

  • Problem Statement: "[기능 또는 컴포넌트]에 해당하는 맥락에서,"가 이 부분이다. 우리가 결정이 필요한 문제가 어떤 것인지 말한다. 위의 예에서는 간단하게 되어 있지만, 맥락을 잘 표현하기 위해서 더 상세히 설명해야 할 수도 있다.
  • Candidate Architecture: 위의 예에서는 [선택된 옵션]과 [대안]이 여기에 포함된다. 위의 예어서는 2개만 표현되어 있지만 3개 이상일 수 있다. 특히, 옵션들은 정말로 어떤 것을 선택할지 고민이 된다면 중요한 Architecture Problem일 수 있다.
  • 요구 사항 및 품질 속성: 많은 경우, Problem Statement에 우리가 다루려고 하는 Functional Scenario가 이미 포함된다. 아키텍처 선택을 할 때 우리가 고려해야 하는 품질 속성의 중요도에 따라 의사 결정을 하는 것이 일반적이다.
  • 보완 필요 부분: "부정적인 결과"를 받아 들인다고 했다. 하지만, 이 부분이 늘 쉽지는 않다. 그렇기 때문에 이 부정적인 결과에 대한 대책이 필요하기도 하다.

패턴들의 구조에서도 설명되지만 문제 기술도 필요하다. 위의 구조와 유사하지만 다음과 같은 형태도 사용한다

다른 형태의 ADR

위와 같이 간단한 형태에서 상세 내용을 기반으로 조정한 ADR이 포함해야 하는 항목을 다시 한번 정리해 보자.

Problem Statement

이 부분을 분리하는 경우는 ADR이 다루려고 하는 문제를 더 상세히 표현하려고 할 때 분리해서 설명하면 좋다. 그렇지 않고, 간단한 문장으로도 표현할 수 있다.

Candidate Architectures

우리가 실제로 고민해야 하는 Architecture적으로 중요한 결정 사항은 무엇일까? 대안들이 2개 이상일 때 Architecture 적으로 중요한 문제일 수 있다. 예를 들어 보자. 어려 이해관계자들이 요구 사항의 충돌이 있을 때, 이 부분을 조정하여 결정해야 하는 사항이다.

간단한 사례

간단한 사례로 "학교 프로젝트를 만들기 위한 발표 자료를 어떻게 준비할까?"를 예로 들어 ADR 형식으로 만들어 보자.

 

  손으로 직접 그림 그리기 파워포인트 슬라이드 사용 큰 포스터로 만들기
장점 (만족하는 품질 속성) 창의적이고 독창적임. 
준비 비용이 적음
수정이 쉽고 깔끔함
팀과 쉽게 공유 가능
시각적으로 강렬함
한눈에 보기 좋음
단점 (손해보는 품질 속성) 시간이 오래 걸림
수정이 어려움
컴퓨터가 필요함
디자인에 시간 소요
운반이 불편함
수정이 어려움
큰 공간 필요

 


이해관계자인 팀원들과 수정이 쉽고 깔끔하게 보이고, 팀원들과 쉽게 공유하고 의견을 주고받을 수 있기 때문에 파워포인트 슬라이드 사용하기로 의사 결정하였다. 이렇게 의사 결정 했을 때에는 디자인에 시간이 소요되고 컴퓨터가 필요하다는 것을 알고 있다. 다지안의 경우는 미리 제공되는 템플릿을 최대한 활용하여 시간을 절약하기로 하였고, 디자인 감각이 있는 팀원이 디자인은 전담하기로 역할 분담을 하였다. 발표에도 컴퓨터가 필요하기 때문에 컴퓨터가 필요하다는 것을 확인하였고 팀원 중 한명이 준비하기로 하였다. 

아마도 다른 옵션들을 선택하는 경우도 있을 수 있다. 제약으로 컴퓨터를 사용하지 못할 경우도 있고, 포스터 세션처럼 운용될 수도 있어서 다른 옵션을 선택해야만 하는 경우도 있을 수 있다. 즉, 다른 옵션들도 의미 없이 그냥 만든 것이 아니고 많은 고민을 해야 하는 옵션들인 것이다.

결론

위에서 살펴 본 것과 같이 ADR에 대해서 살펴 보았고, 아주 간단한 사례를 통해서 여러 옵션들을 도출하고 이를 비교해서 의사 결정을 하는 사례도 살펴 보았다. 

참고 문헌

[1] 올라프 짐머만, 미르코 스토커, 다니엘 뤼브케, 우베 즈둔, 세자레 파우타소, "마이크로서비스 API 디자인 패턴, 쉬운 통합을 위한 결합도 최적화 전략" 에이콘출판, 이승범 (옮긴이)  

개요

리엔지니어링 패턴의 10장 다형성 적용한 조건문 변환은 객체 지향 리엔지니어링 패턴 중에서 조건문을 다형성으로 변환하는 데 중점을 둔다. 이러한 변환은 시스템의 유연성과 유지 보수성을 높이는 데 기여하며, 다양한 조건문을 대체할 수 있는 6가지 주요 패턴을 제시한다. 각 패턴은 특정 상황에서 반복적으로 발생하는 문제를 해결하기 위해 설계되었다.

주요 패턴 요약

  1. 자신 타입 체크 변환하기
    • 클래스의 타입을 검사하는 조건문을 각 타입에 맞는 서브클래스와 다형성 메서드 호출로 대체하여 확장성을 개선한다.
  2. 클라이언트 타입 검사 변환하기
    • 클라이언트 클래스에서 특정 프로바이더 타입을 검사하는 조건문을 제거하고, 각 프로바이더에 새로운 메서드를 추가하여 결합도를 줄인다.
  3. 상태 추출하기
    • 상태(State) 디자인 패턴을 적용하여 객체의 상태에 따라 다른 동작을 수행하도록 하며, 상태를 별도의 클래스 객체로 캡슐화하여 유지 보수성을 향상시킨다.
  4. 전략 추출하기
    • 전략(Strategy) 패턴을 적용해 알고리즘을 캡슐화하고, 조건문을 대체하여 다양한 전략을 동적으로 교체할 수 있도록 한다.
  5. 널 객체 도입하기
    • 널 값을 검사하는 조건문을 널 객체로 대체하여 클라이언트 코드의 간소화 및 가독성을 높인다.
  6. 조건문을 등록으로 변환하기
    • 도구와 클라이언트 간의 결합도를 낮추기 위해 조건문을 등록(Registration) 메커니즘으로 대체하여 모듈화와 유연성을 개선한다.

이 패턴들은 조건문을 다형성으로 변환하여 코드 중복을 줄이고, 향후 시스템 확장을 보다 유연하게 할 수 있도록 한다.

 

참고 문헌
[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"
[2] https://github.com/blcktgr73/OORP

리엔지니어링 패턴의 9장 책임 재배치는 기존 시스템의 클래스와 객체들이 지나치게 많은 책임을 갖거나, 너무 적은 책임만 수행하는 문제를 해결하는 방법론이다. 세 가지 주요 패턴에 대해 이야기 한다.

  1. 동작을 데이터 가까이 이동하기
    데이터 컨테이너에서 행동을 수행하는 클라이언트 클래스에 정의된 행동을 데이터가 있는 곳으로 이동하여 캡슐화를 강화하는 방식이다. 이를 통해 클라이언트가 데이터 구조에 대한 직접적인 의존을 줄이고, 코드 중복을 줄이는 효과가 있다. 이 패턴은 데이터 컨테이너를 더욱 객체답게 만들고, 클라이언트 코드의 유지 보수를 쉽게 한다.
  2. 탐색 코드 제거하기
    객체 간 탐색을 줄여 클래스 간 결합도를 낮추는 패턴이다. 특정 객체의 속성에 접근하기 위해 여러 단계를 거쳐야 할 경우, 탐색 코드를 데이터 컨테이너 내로 옮겨 캡슐화를 높인다. 이를 통해 클래스 간의 불필요한 종속성을 줄이고, 변경의 영향을 최소화할 수 있다.
  3. 신 클래스(God Class) 분할하기
    하나의 클래스에 지나치게 많은 책임이 집중된 경우, 이를 여러 작은 클래스로 분리하는 방법이다. 신 클래스는 여러 기능을 담당하며, 시스템의 모든 제어를 맡아 비대해진 클래스이다. 이를 분할하여 각 기능을 적절한 클래스에 배분함으로써 유지 보수성을 높이고, 객체 지향 설계를 강화할 수 있다.

이 세 패턴은 책임을 올바르게 분배하고, 코드의 응집도와 캡슐화를 개선하는 데 중점을 두고 있다.

 

참고 문헌
[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"
[2] https://github.com/blcktgr73/OORP

+ Recent posts