[1]의 4장 초기 이해에서는 소스 코드의 초기 분석을 위한 세 가지 주요 패턴을 제시한다. 퍼시스턴트 데이터 분석하기, 디자인 추측하기, 예외적인 엔터티 연구하기가 그것이다. 각 패턴은 리엔지니어링 프로젝트의 성공적인 진행을 위한 필수적인 단계이다.

퍼시스턴트 데이터 분석하기

  • 의도: 데이터베이스 시스템 내부에 보관해야 할 중요한 개체를 식별하고 이해한다.
  • 문제: 귀중한 데이터는 외부 저장 장치에 보관되어야 하지만, 정리되지 않은 데이터와 혼재될 수 있다.
  • 해결:
    1. 모든 테이블 이름을 열거하여 초기 모델을 준비.
    2. 각 테이블에 대해 열 이름을 수집하고 속성으로 추가.
    3. 후보 키 및 외래 키 관계를 분석.
    4. 상속 관계를 유추하여 클래스 다이어그램을 도출.
    5. 데이터 샘플과 SQL 문을 통해 검증.
  • 장점: 팀 커뮤니케이션 개선, 가치 있는 데이터 추출.
  • 단점: 범위 제한, 정크 데이터 포함, 전문 지식 필요.

디자인 추측하기

  • 의도: 소스코드에서 디자인 개념을 복구하여 가설을 검증하고 구체화한다.
  • 문제: 많은 디자인 개념이 있으며 프로그래밍 언어에서 이를 표현하는 방법이 다양하다.
  • 해결:
    1. 초기 가설 역할을 하는 클래스 다이어그램 작성.
    2. 클래스, 연산, 속성 이름을 소스 코드에서 찾아 가설 검증.
    3. 불일치를 기반으로 클래스 다이어그램을 조정.
    4. 만족스러운 다이어그램을 얻을 때까지 반복.
  • 장점: 대규모 객체 지향 프로그램에 유리, 저렴한 리소스 투자.
  • 단점: 전문 지식 필요, 시간이 많이 소요됨.

예외적인 엔터티 연구하기

  • 의도: 시스템에서 예외적인 엔터티를 식별하고 분석하여 전체 구조를 이해한다.
  • 문제: 예외적인 엔터티는 일반적인 패턴을 따르지 않으며, 특별한 처리가 필요하다.
  • 해결:
    1. 예외적인 엔터티를 식별.
    2. 해당 엔터티의 특성과 동작을 분석.
    3. 다른 엔터티와의 관계를 이해하여 시스템 전체의 구조를 파악.
  • 장점: 시스템의 비정상적인 부분을 이해하고 해결하는 데 도움.
  • 단점: 예외적인 상황을 처리하기 위한 추가 분석이 필요.

이 세 가지 패턴은 소프트웨어 리엔지니어링 프로젝트의 초기 분석 단계에서 시스템을 이해하고 문서화하는 데 필수적인 방법들이다. 이를 통해 프로젝트의 안정적인 기반을 구축하고, 성공적인 진행을 보장할 수 있다. [2]에서 번역된 내용을 찾을 수 있다.

 

참고 문헌

[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"

[2] https://github.com/blcktgr73/OORP 

[1] 의  3장 초기 접근 방법에 다음과 같은 리엔지니어링 프로젝트 예제를 이용해서 실제 예시로 패턴에 대해 설명한다.

  • 시나리오: 사용자 팀은 의료 소프트웨어 시스템인 proDoc을 개발하고 있으며, 경쟁사인 XDoctor의 인터넷 기능을 proDoc에 통합하려고 합니다.
  • 주요 과제: 시스템을 통합하고 리엔지니어링하기 위해 첫 번째 평가와 계획을 수립하는 것입니다.

 

주요 요구사항

  1. 규모 문제: 레거시 시스템이 크고 복잡하므로 이를 관리 가능한 부분으로 나누어야 한다.
  2. 시간 부족: 프로젝트 초기에는 시간을 낭비하지 않도록 주의해야 한다.
  3. 불완전한 지식: 초기에 중요한 결정을 내릴 때 불완전한 지식으로 인해 잘못된 결정을 내릴 수 있다.
  4. 다양한 이해관계: 여러 이해관계자들이 서로 다른 의제를 가지고 있을 수 있다.

 

패턴 적용:

  • 유지보수자와의 담소나누기: 시스템의 역사적, 정치적 맥락을 이해하기 위해 유지보수자와 논의한다.
  • 한 시간 안에 모든 코드 읽기: 소프트웨어 시스템의 상태를 빠르게 평가하기 위해 집중적으로 코드를 검토한다.
  • 모의 설치 수행하기: 리엔지니어링 적합성을 평가하기 위해 시스템을 실제로 설치하고 실행해 본다.
  • 문서 스키밍하기: 관련 문서를 빠르게 검토하여 중요한 정보를 파악한다.
  • 데모 중 인터뷰하기: 시스템을 사용하는 사람들과 인터뷰를 통해 추가 정보를 수집한다.

 

예시

예시에서는 앞에서 설명한 것의 사례에서 일어 났던 경험을 해당 패턴에 연계하여 이야기 한다.

  • XDoctor 인수: XDoctor의 개발팀에서 유일하게 남은 데이브와의 대화를 통해 중요한 기술적 정보를 얻고, 두 시스템을 통합하는 계획을 세훈다.
  • 코드 검토: Java와 C로 작성된 코드를 검토하여 시스템의 구조와 품질을 평가한다.

 

결론

리엔지니어링 프로젝트를 성공적으로 수행하기 위해서는 초기 단계에서 정확한 평가와 계획이 중요하며, 이를 위해 다양한 패턴을 적용하여 시스템의 상태와 문제를 파악해야 한다고 이야기한다. 이 패턴들을 읽어 보면, 실재로 경험한 듯한 것들이 많다. 특히, 유지보수자와 담소나누기, 모의 설치하기 등은 마치 내 경험을 몰래 들여다 본 것 같은 느낌도 들 정도였다. 다른 것들의 경우도, 일부는 경험한 듯 하고 시간 제약을 두고 하는 것도 눈에 띄는 이야기였다. 무엇보다도 사회적 맥락에서 접근하는 패턴은 이 부분이 매우 실용적인 것이라는 생각도 많이 들었다. [2]에 번역 내용이 올라가 있다.

 

참고 문헌

[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"

[2] https://github.com/blcktgr73/OORP 

[1]의 2장 방향 설정하기는 리엔지니어링 프로젝트의 방향 설정에 관한 내용을 다루고 있다. 팀 내에서 공통된 목적의식을 확립하는 방법과 함께 리엔지니어링 프로젝트를 효과적으로 진행하는 데 필요한 다양한 전략과 맥심(지침 원칙)을 소개하고 있다.

주요 내용은 다음과 같습다.

  • 맥심에 동의하기 - 프로젝트의 핵심 우선순위를 설정하고 팀이 올바른 방향으로 나아갈 수 있도록 돕는 지침과 원칙을 개발하는 과정다.
  • 내비게이터 지정 - 아키텍처 비전을 유지할 수 있도록 특정 인물을 '내비게이터'로 지정하는 전략이다.
  • 원탁 회의에 말하기 - 정기적인 원탁 회의를 통해 프로젝트 상태에 대한 팀 인식을 유지하고 정보를 공유하는 방법이다.
  • 가장 가치 있는 것 먼저 하기 - 문제 해결에 있어 가장 중요하고 가치 있는 부분부터 시작하는 전략이다.
  • 증상이 아닌 문제 수정하기 - 문제의 증상이 아닌 근본 원인을 해결함으로써 더 효과적인 리엔지니어링을 도모하는 접근법이다.
  • 고장이 나지 않으면 수정하지 않기 - 실제로 문제를 일으키고 있는 부분만을 수정하는 실용적 접근 방식이다.
  • 간단하게 유지하기 - 과도한 복잡성을 피하고, 간단하고 효과적인 솔루션을 구현하는 전략이다.

각 절에서는 이러한 원칙들을 실제로 적용하는 방법과 예상되는 도전, 그리고 팀 내부의 동기 부여 및 관리 방법에 대해 논의한다. 이를 통해 리엔지니어링 프로젝트가 보다 성공적으로 수행될 수 있도록 설계된 지침서로 사용할 수 있다.

 

[2]에 번역 내용이 올라가 있다.

 

참고 문헌

[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"

[2] https://github.com/blcktgr73/OORP 

 

아키텍처 드라이버는 시스템의 아키텍처에 영향을 미치는 주요 요인(Driver)이다. 이러한 드라이버는 아키텍처 결정을 내리는 데 중요한 역할을 하며, 요구사항(Requirement), 제약사항(Constraint), 원칙(Principle) 등을 포함할 수 있다. 소프트웨어 아키텍처 분야의 다양한 전문가와 저자들은 아키텍처 드라이버에 대해 논의하였는데 주요한 내용들을 정리해 보자.

아키텍처 드라이버를 언급하는 주요 인물들

  1. 그래디 부치 (Grady Booch)
    • 공통점:
      • 요구사항(Requirement)과 제약사항(Constraint)을 이해하는 것이 중요하다고 강조한다.
      • 성능, 확장성, 보안과 같은 품질 속성(Quality Attribute)의 역할을 강조한다.
    • 차이점:
      • 아키텍처 결정 과정과 UML과 같은 모델링 언어 사용에 더 중점을 둔다.
  2. 메리 쇼와 데이비드 갈란 (Mary Shaw and David Garlan)
    • 공통점:
      • 아키텍처 스타일(Architectural Style)과 패턴(Pattern)이 아키텍처 드라이버의 일부임을 강조합니다.
      • 기능적 요구사항(Functional Requirement)과 비기능적 요구사항(Non-functional Requirement 혹은 Quality Attribute) 모두를 다룰 필요성을 강조한다.
    • 차이점:
      • 아키텍처 스타일을 분류하고 이해하는 데 중점을 두는 더 학문적이고 이론적인 관점을 제공한다.
  3. 바스, 클레멘츠, 카즈먼 (Bass, Clements, and Kazman) - "Software Architecture in Practice" 저자들
    • 공통점:
      • 품질 속성(Qaulity Attribute)이 아키텍처 결정에 중요한 역할을 한다고 강조한다.
      • 이해관계자의 우려가 아키텍처를 형성하는 데 중요한 역할을 한다고 강조한다.
    • 차이점:
      • Attribute-Driven Design (ADD) 방법 등 아키텍처 결정을 평가하고 문서화하는 자세한 프레임워크를 제공한s다.
  4. 마틴 파울러 (Martin Fowler)
    • 공통점:
      • 요구사항과 제약사항이 아키텍처 결정에 중요한 역할을 한다고 인정한다.
      • 아키텍처의 유연성을 유지하여 변화하는 드라이버에 적응하는 것이 중요하다고 강조한다.
    • 차이점:
      • 실무 경험과 애자일 방법론을 통해 아키텍처 드라이버를 다루는 데 더 중점을 둔다.

공통점

  • 품질 속성(Quality Attribute): 모든 저자는 품질 속성(예: 성능, 보안, 유지보수성)이 중요한 아키텍처 드라이버임을 강조한다.
  • 이해관계자의 우려: 다양한 이해관계자의 우려를 이해하고 해결하는 것이 중요하다고 일관되게 강조한다.
  • 기능적 및 비기능적 요구사항: 두 가지 요구사항 모두 아키텍처 결정을 내리는 데 기본적이라고 인식한다.

차이점

  • 방법론 및 프레임워크:
    • 그래디 부치는 모델링 언어와 프로세스에 중점을 둔다.
    • 바스, 클레멘츠, 카즈먼은 ADD와 같은 특정 프레임워크를 제공한다.
    • 마틴 파울러는 애자일 실천과 현실 세계의 적응성을 강조한다.
  • 관점:
    • 카네기 멜론대 소프트웨어 엔지니어링 인스티튜트(Carnegie Mellon University Software Engineering Institue, CMU SEI)의 메리 쇼와 데이비드 갈란은 더 이론적이고 학문적인 접근을 취한다.
    • 마틴 파울러는 실무자 지향적 관점을 제공한다.
  • 프로세스 vs. 패턴에 대한 강조:
    • 그라디 부치와 마틴 파울러는 프로세스와 적응성에 중점을 둔다.
    • 메리 쇼와 데이비드 갈란, 바스 등은 아키텍처 스타일과 패턴을 이해하고 활용하는 데 중점을 둔다.

요약

요약하자면, 품질 속성, 이해관계자의 우려, 기능적 및 비기능적 요구사항의 중요성에 대한 공통점이 있지만, 방법론, 관점, 특정 강조점에서 차이가 있다. 그라디 부치는 프로세스와 모델링에 중점을 두고, 메리 쇼와 데이비드 갈란은 이론적 이해를, 바스 등은 프레임워크를, 마틴 파울러는 실무와 애자일 방법론을 강조한다.

소프트웨어 아키텍처를 고려할 때 주요한 무기 중 하나가 추상화(abstraction)이다[1]. 추상화는 문제를 축소하여 해결하기 더 쉬운 작은 문제로 만들어 규모와 복잡성의 문제를 효과적으로 해결하게 한다. 여기서도 LLM(Large Language Model)의 여러 측면에서의 추상화를 통해서 이를 활용하는 Software Architecture에 대해서 이해도도 높이고 이를 활용해 설계하는데도 도움이 될 수 있기를 기대해 본다.

 

프로그래밍 모델로서의 LLM

LLM을 가지고 Prompt를 작성해서 작업을 하는 것은 마치 우리가 컴퓨터 프로그래밍하는 것과 비교가 가능하다. 아래 그림[2]이 이 부분을 잘 보여 준다. LLM은 이미 트레이닝을 마치거나 우리가 원하는데로 파인 튜닝을 마친 것이라고 볼 수 있다. 여기에 사용자의 Prompt를 전달하는 것까지 프로그래밍하는 것과 유사하다는 비교를 볼 수 있다. 물론, Prompt가 자연어에 가깝고 결과가 프로그래밍과는 조금 다르게 나올 수 있지만 LLM과 Prompt를 컴퓨터 프로그래밍과 매치 시켜보는 구조는 LLM을 가지고 원하는 작업하는 것에 대한 가장 간단한 추상화로 볼 수 있다.

 

[2] Program Model vs Gen AI Model

 

인간 인지 구조와 비교

LLM과 비교하기 위해서 인간 인지 메모리 모델을 살펴보자[3]. 결국은 기억/메모리 구조인데, 감각기억 (Sensory Memory), 단기기억 (Short-term Memory), 장기기억 (Long-term Memory)으로 구성된다.

 


감각기억 (Sensory Memory)은 시각, 청각 그리고 촉각과 같은 감각 기관에서 입수된 정보를 잠시 저장했다가 단기 기억으로 저장되는데 일부는 장기기억으로 전달 된다고 한다.이 단기 기억은 정보가 짧은 시간 동안 저장되고 처리되는데. 작업기억(Working Memory)으로 불리며, 정보의 일시적 저장과 조작을 담당한다. 장기 기억은 정보를 오랜 기간 동안 저장하는데, 크게는 명시적 기억(Explicit Memory)과 암묵적 기억(Implicit Memory)으로 나뉜다.

 

LLM은 구조적으로는 비슷해 보인다. 사용자가 LLM에 입력으로 Prompt를 제공하면 이는 마치 사람의 작업 기억 처럼 컨텍스트 윈도우(Contexnt Windows) 내의 내용만 참조하고 처리한다. LLM이 많은 내용을 학습하고 이를 통계적인 절차를 통해서 말이 되도록 생성한다. 

 

[4] LLM 구조

 

다시 말하자면, LLM이 사람의 장기기억 처럼 동작하지는 않지만, 유사성이 있기 때문에 이를 잘 활용하는 것이 필요하다. 첫 째로 대량의 정보를 저장하고 있다. 즉, 대량의 텍트스 데이터를 학습하여 패턴과 지식을 내재화하였다. 그리고, 학습을 통해서 지식이 형성되어 있기 때문에 사용자의 입력에 대해 예측하고 그 결과를 제공한다. 그렇기 때문에, LLM을 "말많은 뉴비(Newbie)"로 비유되기도 한다.

 

LLM 애플리케이션 아키텍처

LLM 어플리케이션의 레퍼런스 아키텍처의 구성 요소를 [5]에서 잘 보여 준다. 하지만, 여러 항목이 있어서 너무 복잡해 보이기도 한다. 이를 간략화 하면 아래와 같다고 볼 수 있다.

 

Simplified LLM App Architecture


LLM의 경우는 미리 트레이닝을 해야 하기 때문에 최신 자료들에 대해서 처리하지 못한다. 24년 6월의 경우도, 23년 10월까지 업데이트 되어 있다고 한다. 이 부분의 한계를 극복하기 위한 것이 Retrieval Augmented Generation (RAG)이다. [5]에도 있지만, Embedding Model, Vector Database와 같은 개념이 포함된다. 이 부분에 대해서는 따로 더 자세히 다뤄 보겠다. LLM의 경우도, 상용화를 위한 Foundatation Model 뿐만 아니라 사용자와 interaction을 위한 Cache 그리고 부적절한 생성 내용을 filtering하기 위한 모듈도 포함되어 있.

 

마치며.

LLM과 관련된 작업 혹은 어플리케이션의 추상화를 통해서 구조적인 측면을 프로그래밍 언어 관점, 인간의 인지적 모델과 비교, 최근의 LLM 기반 어플리케이션 모델의 관점에서 살펴보았다. 어플리케이션의 관점이나 문제의 관점에서 또한 추상화와 구조의 변경이 필요하겠지만, LLM을 기반으로 하는 시스템의 소프트웨어 아키텍처 관점에서 좋은 시작점이 될 수 있지 않을까 기대해 본다.

 

참고문서

[1] 조지 페어뱅크스 저/이승범 역, "적정 소프트웨어 아키텍처-리스크 주도 접근법" 한빛미디어

[2] Prompt Engineering이란?, https://velog.io/@w0_0727/i4uh3e4e

[3] Eduardo Camina,and Francisco Güell, " Psychological Basis of Memory: Current Models and Their Origins," https://www.frontiersin.org/journals/pharmacology/articles/10.3389/fphar.2017.00438/full

https://a16z.com/emerging-architectures-for-llm-applications/

[4] Sunil Ramlochan, "Statistical or Sentient? Understanding the LLM Mind - Part 1 - Memory" https://promptengineering.org/statistical-or-sentient-understanding-the-llm-mind/

[5] Nicole Choi, "The architecture of today’s LLM applications", https://github.blog/2023-10-30-the-architecture-of-todays-llm-applications/?fbclid=IwAR2daV0oLZAU8ZS45SeL5Wh7aVDcscJBL1hsEBBRVXW2rywoeqd6AnfwzJg

 

Object-oriented Reengineering Pattern[1]의 저자인 세르게이 디마이어의 허락을 받아 번역을 시작한다. 전에 김창준님이 내가 관심이 있겠다고 소개해서 알게된 책이기도 하다. 이 책은 출판이 된적이 있지만, 크리에이티브 커먼즈로 공개되었다. 그렇다 하더라도, 번역하는데 허락을 받을 필요가 있다고 생각해서 저자에게 연락을 하여 확인하였다. 1장의 리엔지니어링 패턴을 번역하면서 [2]에 공유하고 내용을 요약해서 적어 본다.

 

1장의 내용은 소프트웨어 리엔지니어링(Software Reengineering)에 대해 다루고 있다. 특히, 레거시 시스템의 문제를 식별하고 개선하는 다양한 방법을 포함하며, 이를 통해 시스템을 더 유지보수가 가능하고 최신 요구 사항에 대응 가능하도록  조정하는 과정으로서 리엔지니어링을 설명한다. 주요 내용은 다음과 같다.

 

  • 리엔지니어링의 필요성: 레거시 소프트웨어 시스템이 비즈니스에 중요함에도 불구하고 많은 비용이 들어 업그레이드나 교체가 어렵기 때문에 리엔지니어링이 필요하다.
  • 리엔지니어링의 목적: 레거시 시스템의 복잡성을 줄이고, 적절한 비용으로 시스템을 계속 사용하고 적응할 수 있게 하는 것이다.
  • 리엔지니어링의 이유: 성능 개선, 시스템을 새 플랫폼으로 이전하기 위함, 유지보수 비용 절감, 시스템에 대한 지식 문서화 등 여러 가지 구체적인 이유가 있다.
  • 리엔지니어링 과정: 문제가 있는 레거시 시스템을 식별하고, 개선 방법을 모색하여 구현하는 과정을 포함한다. 이 과정에서 리버스 엔지니어링과 리엔지니어링의 차이점을 설명한다.
  • 리엔지니어링 패턴: 리엔지니어링 과정에서 사용되는 패턴의 양식을 소개한다.

 

참고 문헌

[1] Serge Demeyer et al., "Object-oriented Reengineering Patterns"

[2] https://github.com/blcktgr73/OORP 

마틴 파울러는 [1]에서도 소개했지만, "Refactoring"으로 유명하고, 여러 저서의 저자이기도 하다. 그는 애자일리스트로 엔지니어링 실천법(engineering practices)에 집중하는 익스트림 프로그래밍(Extreme Programming, XP)의 추종자이다.
 
마틴 파울러의 웹사이트에서 여러가지 소개하고 있는데, 소프트웨어 아키텍처에 대해 설명하는 글[2]도 포함되어 있다. 여기서 그는 소프트웨어 아키텍처는 소프트웨어 "시스템의 중요한 내부 설계"를 의미한다고 정의 하며, 좋은 아키텍처는 시스템이 "진화"할 수 있도록 지원해야 한다고 강조한다. 이것이 마틴이 이야기하는 애자일 소프트웨어 아키텍처의 핵심이라고도 할 수 있겠다.마틴은 이 글에서 팀이 좋은 아키텍처를 만드는 방법과 아키텍처 사고를 어떻게 개발 조직에서 장려해야 하는지에 대해서도 이야기하는데 그내용도 살펴 보자.

아키텍처의 진화

마틴 파울러의 웹사이트에서 진화적 아키텍처는 요구사항의 변화를 수용하고 지속적인 피드백을 통해 시스템이 개선될 수 있도록 지원한다고이야기 한다. 그리고,  소프트웨어 아키텍처가 일회성 계획이 아닌 지속적인 과정으로 설명한다. 그리고, 이를 위해서 다음 사항에 대해서 강조한다.
 

  • 반복적 개발과 피드백 루프: 소프트웨어 개발 과정에서 짧은 반복주기를 통해 지속적으로 통합하고 테스트하는 방식을 사용함으로써, 아키텍처를 점진적으로 발전시키는 방법을 강조한다. 이는 고도의 협업과 지속적인 개선을 가능하게 한다.
  • 피트니스 펑션의 활용: 아키텍처의 상태를 모니터링하고 진화의 방향을 가이드하는 데 사용되는 '피트니스 펑션' 개념을 사용하여 아키텍처의 건강을 측정하고 관리한다.
  • 데이터 관리의 중요성: 진화적 아키텍처에서는 오래 지속되는 데이터의 처리가 종종 간과되기 쉬운 문제로, 이에 대한 강조를 통해 데이터 관리와 관련된 전략을 체계적으로 다루어야 함을 강조한다.
  • 마이크로서비스와 도메인 주도 설계: 큰 단일 시스템을 더 작고, 독립적으로 관리 가능한 마이크로서비스로 분해하는 과정에서, 중요한 비즈니스 기능을 식별하고 이를 기반으로 서비스를 분리하는 전략을 사용한다. 이는 시스템의 유연성을 높이고, 변경 관리를 용이하게 한다.


마틴이 늘 강조하듯이 이러한 점들은 소프트웨어 아키텍처가 단순히 기술적인 문제가 아니라, 지속적인 비즈니스 가치를 창출하고 유지하는 중요한 역할을 한다는 것을 강조한다. 진화적 아키텍처 접근 방식은 변화하는 비즈니스 요구와 기술 환경에 효과적으로 대응할 수 있도록 돕는다고 설명한다.
 

팀이 만드는 좋은 아키텍처

마틴은 아키텍처가 팀에서 나온다고 믿는데, 팀이 좋은 아키텍처를 만드는 방법에 대해 다음과 같이 설명한다.

  • 지속적인 학습과 피드백: 팀은 반복적인 피드백 루프를 통해 아키텍처를 지속적으로 개선해야 한다.
  • 협업과 소통: 개발자 그리고 여러 이해관계자 간의 긴밀한 협업이 필요하다.
  • 작은 변경의 관리: 아키텍처를 점진적으로 변화시켜야 하며, 이는 작은 단위의 변경을 통해 이루어져야 한다.
  • 자동화와 테스트: 지속적인 통합과 테스트 자동화를 통해 아키텍처의 품질을 유지해야 한다

 

개발조직이 아키텍처적 사고를 가지는 방법

팀이 아키텍처 사고를 가지기 위해서 마틴은 다음 사항들을 강조하고 있다:

  • 교육과 훈련: 팀원들에게 아키텍처 원칙과 패턴을 교육한다.
  • 협업 문화: 개발자 간의 적극적인 협업을 촉진하여 아키텍처 관련 논의를 장려한다.
  • 피드백 루프: 정기적인 코드 리뷰와 피드백을 통해 아키텍처 품질을 유지하고 개선한다.
  • 실험과 혁신: 새로운 아이디어와 접근 방식을 실험할 수 있는 환경을 조성한다.

 

참고 문서

[1] 로버트 마틴 vs. 마틴 파울러, https://technical-leader.tistory.com/94
[2] Martin Fowler, "Software Architecture Guide", https://martinfowler.com/architecture/

애자일 소프트웨어 개발의 경우, 약점으로 알려져 있는 것이 개발하는 소프트웨어의 규모이다. 이러한 측면에서 다양한 접근 방법이 제시 되고 있다. 이 부분에 대해서 살펴 보자.

 

규모 확대 전략 (Scale up strategy)의 종류

애자일 소프트웨어 개발을 대규모로 확장하는 접근 방법으로 다음과 같은 것들이 알려져 있다.

1. Scaled Agile Framework(SAFe)[1]

2. Large Scale Scrum(LeSS)[2]

3. Disciplined Agile Delivery(DaD)[3]

4. Nexus framework[4]

5. Scrum@Scale[5](Scrum of Scrums[6], Spotify model[7])

 

이렇게 여러가지가 있지만, 소프트웨어 아키텍처에 관련해서 이야기 하는 것들은 1~3번이다.

 

4번과 5번은 Scrum이 반복을 기반으로 한 애자일 프로세스의 규모확장성(Scalability)에 대한 이야기로 볼 수 있다. 즉, 스크럼이 작은 팀(예를 들어 피자 두 판)만 가능하다고 하면 큰 규모의 소프트웨어 개발을 하는 조직을 어떻게 애자일하게 만들것이냐는 측면에 대한 접근인 것이다. 다른 접근 방법과 다르게 4번과 5번은 여전히 스크럼을 기반으로하고 있으므로 더 애자일한 측면이 있고, 다른 접근 방법들은 산출물이나 스크럼에서 이야기 하지 않는 다른 역할들을 정의하는 규율 기반(Disciplined approach)으로 애자일과는 다른 관점의 항목들이 추가된다고 이야기 할 수 있다.

 

4번 Nexus framework와 5번 Scrum@Scale의 차이점은 조직을 어떻게 구성하느냐 접근 방식이라고 볼 수 있다. Nexus는 정의부터 3개에서 9개의 스트럼팀을 코디네이트하는 것이라고 하고, Scrum@Scale은 조직 전체를 나누어 여러 스크럼의 스크럼을 단계적으로 만들어간다[8].

 

이후에는, 1~3번의 세가지 접근 방법에서 이야기 하는 소프트웨어 아키텍처에 대해서 살펴 보자. 대부분의 내용은 [9]에서 설명되어 있는 것들의 요약이다.

 

비슷한점

  • 애자일 아키텍처의 중요성: SAFe, DaD, LeSS 모두 애자일 아키텍처를 중시하며, 시스템을 지속 가능하고 확장 가능하게 설계하는 데 중점을 둔다.
  • 점진적 개발: 이들 프레임워크는 모두 변화를 수용하고 점진적으로 시스템을 개발하고자 하는 애자일의 원칙을 따른다.
  • 분산된 의사결정: 의사결정의 분산을 통해 빠른 반응과 유연성을 높이는 것을 강조한다.

 

다른점

  • 프레임워크의 구조: SAFe는 포트폴리오, 솔루션, 프로그램, 에센셜, 팀의 5단계 구조를 제공하는 반면, DaD는 시작, 구축, 전환의 3단계로 구성되어 있고, LeSS는 기본적인 스크럼 방식을 확장하여 사용한다.
  • 철학 및 접근방식: SAFe는 구조적이고 포괄적인 접근을, DaD는 맞춤형 접근을, LeSS는 최소한의 프로세스를 중심으로 한 접근을 제공한다.
  • 역할과 책임: LeSS는 다른 프레임워크에 비해 역할 수를 줄이는 방향을 강조하여 복잡성과 오버헤드를 감소시키고자 한다. 반면 SAFe와 DaD는 좀 더 많은 역할과 구조를 제안한다.

마무리하며...

애자일 개발방법의 규모 확장법이 이렇게 많다는 건 정답이 없다는 반증일 것이다. 특히, 아키텍처를 다루는 3가지 접근 법은 비교해보면 특징이 드러난다. SAFe는 관리적인 측면을 강조하고 있고, LeSS는 Scrum의 자연적인 확장을 기대며 팀에 기댄다. 서로 양극단이라고 한다면, DaD는 그 중간 즈음에 위치한다고 볼 수 있겠다.

 

참고 자료

[1] Scaled Agile Framework, https://www.scaledagileframework.com/

[2] Large Scale Scrum, https://less.works/

[3] Disciplined Agile Delivery, https://www.pmi.org/disciplined-agile/process/introduction-to-dad

[4] Scaling Scrum with Nexus, https://www.scrum.org/resources/scaling-scrum

[5] The Official Scrum@Scale Guilde, https://www.scrumatscale.com/scrum-at-scale-guide/

[6] Scrum of scrums, https://www.atlassian.com/agile/scrum/scrum-of-scrums

[7] Spotify and Scrum@Scale, https://www.scruminc.com/spotify-model-scrum-at-scale/

[8] Scrum@Scale An Introduction, https://medium.com/serious-scrum/scrum-scale-an-introduction-432bb0402488

[9] 라제시 RV 저자(글) · 김모세 번역, "애자일 소프트웨어 아키텍트의 길, 소프트웨어의 지속적인 설계를 통한 진화", 에이콘출판 · 2022년 10월 28일

 

 

J님이 생각하고 있던 문제의 경우는 기존 서비스에서 필요한 부분을 추출하여 신규 서비스에 적용하여 활용할지가 초기에 공유한 고민이었다. 신규로 서비스 제공하려고 하는 것은 국내의 경우 판매 사이트가 없어 영업부서 분들이 Excel, 이메일, 전화를 할용하여 진행되던 것을 서비스화 하여 이를 기존 서비스와 연동하고 또한 이를 제품으로서도 판매하려고 하는 것이었다.

이야기를 나누다 보니 결국 신규로 확장 구현하시는 모듈과 기존의 시스템을 어떻게 연계할 것인가에 대한 고민이 크셨던 것 같다. 특히, 기존 시스템은 회사에서 활용하고 계신 시스템이라 크게 변동이 일어나지 않기를 바라시는 것으로 파악되었다. 그러면서도 신규로 개발되는 시스템과의 효과적인 연동에서 수정이 많이 발생될 것으로 파악하시면서 결국 가장 중요하게 생각하시는 수정 용이성(modifiability)에 집중하시는 것이 중요하다고 생각이 되었다.

논의하면서 J님이 얻는 아키텍처적 결정은 Flux 혹은 MVVM 모델로 가져가는 것이었다. 이는 J님도 알고 계셨던 MVC에서 로직 처리의 흐름을 한방향으로 가져가게 한다는 추가 아이디어를 공유함으로서 많은 에너지를 얻으신 것 처럼 보였다. 기존 서비스와 추가 서비스의 구조와 시나리오를 보았을 때에는 MVC와 같은 구조에 빗대어 보는 것이 이해가 쉬웠다. 신규로 서비스를 추가하려는 것이 기존 서비스를 View가 되고,  신규로 추가하려는 서비스가 Model과 Controller 역할을 하는 것으로 파악되었다. 그렇다면, 기존 서비스는 고정하고 우리 서비스는 계속 변하더라도 영향이 덜 받는 구조로 만들어야 한다고 함께 판단하게 되였다.

Legacy System. 저희 회사에서도 종종 기존의 시스템으로 다루기 어려운 것이라는 느낌이 강하지만, 결국은 담당하고 있는 저희들은 Asset이기도 하다. 하지만, 여기에 숨겨진 Debt가 어떤 것인지 몰라 두려움을 느끼게 하기도 하는 것 같다. 결국은 우리가 집중해야 할 곳이 어디인지 찾고, 그 부분에 대해서 어떻게 대응할 것인지 판단하는 것이 Legacy System을 Asset으로 만드는 방법이라고 아닐까 생각한다.

iOS를 기반으로 사진을 편집하는 기능을 포함하는 앱을 개발하는 D의 사례를 살펴 보자. 이 분은 본인 포함 3명이 개발을 하는 팀인데, 스크럼기반으로 스프린트를 운영하면서 요구 사항들을 지속적으로 앱에 적용하고 있었다. 이미 리팩토링을 통해서 구조를 개선을 하였지만, 여전히 새로운 요구 사항에 대한 중복 코드가 늘고 유연하게 대처 안되고 비즈니스 로직 분리하여 추상화 중복 코드 제거하고 싶어 하였다. 궁극적으로는 시장 릴리즈 이후 품질 이슈나 QA 중 예상치 못한 이슈를 최소화 하시고 싶어했다.

원 포인트 세션 중에 문제를 구체화 하고 날카롭게 하는 것이 필요해 보였다. 이야기 할 수록 이상했던 부분은 어떻게 해야 할지 다 알고 계신 것이 보였다. 문제 중 하나는 Undo/Redo하면서 중복 호출되는 코드의 상세 사항으로 들어 갈 수록 이 부분을 리팩터링하면서 효율화 하고 싶다는 것을 알 수 있었다. 즉, 해야 할일에 대해서는 이미 알고 있어 보였다. 즉, 관련 부분을 추상화하고, 중복 코드도 제거하여 향후 코드 파악이쉽고, 추가 요구사항에 대응이 용이하게 하는 것이다. 하지만, "실행"하는 것이 문제였다. 여러 이야기가 있었지만 본인 포함 3명의 개발자로 신규 요구 사항을 스프린트 내에서 소화하고 이러한 부분을 함께 진행하시는 것에 부담이라는 것이다. 이러한 상황이라면 어떻게 할 수 있을까?

우리는 "작게 해볼 수 있는 것"을 찾아 보게 되었다. 작게 나누어 해볼 수 있는 방법에 대해 이야기 나누었다. 그러면서도, 제품으로 적용되어 진행 될 수 있도록 하는 것이 목표였다. 이렇게 하기 위해서 중복되더라도 작게 개선해 가는 방법에 대해서 상세하게 이야기를 나눴다. 개선해야 하는 객체들이 여러가지가 있었는데, 변경하는 도중에는 개선한 것과 개선하지 않은 객체들이 중복해서 존재하지만 개선이 되어 가는 방법에 대해서 이야기 나누었다. 이렇게 하기 위해서 이 작게 나뉜 리팩터링 작업을 스크럼의 백로그(Backlog)로 만드는 방법에 대해서 이야기 나누었다. 그러기 위해서, 이해 관계자(Stakeholder)와 이를 공유하는 것도 이야기 나누었다. 이러한 논의를 통해 D는 좀 더 자신감을 얻었다. 

상품화 된 소프트웨어 제품을 개선하는 것에 대해서 "달려가는 기차의 바퀴를 바꾸는 일"이라는 비유를 들은 적이 있다. 상황의 어려움도 있지만, 문제와 관련된 다양한 리스크가 많기 때문 일 것이다. 이를 위해서는 우리가 리스크에 대한 걱정을 줄이는 것이 중요하다. 이 부분을 통해 자신감이 높아지는데 도움이 되기 때문이다. 또한, 이렇게 우리가 걱정되는 것이 있다면 작게 시도해 보고 실패하고 계속해서 시도하면서 우리가 개선하는 것에 대해서 학습하는 것이 효과적이다. 수백kg에 해당하는 펀치를 한번에 받아 내는 것 보다는 수백g의 작은 펀치를 여러 번 나눠 맞는 것이 끝까지 살아 남는데는 더 나은 선택이기 때문이다.

+ Recent posts