소프트웨어 아키텍쳐 (3) 모듈성

GJ·2023년 1월 4일
0
post-thumbnail

한빛미디어의 소프트웨어 아키텍쳐 101을 요약 정리했습니다.
이 포스팅은 개인 학습 목적으로 작성되었으며, 한빛미디어 도서 저작권 가이드라인을 준수하였습니다.
도서에 대한 자세한 정보는 아래 링크에서 확인 가능합니다.
https://www.hanbit.co.kr/store/books/look.php?p_code=B1494466807

모듈성이란 무엇인가

  • 사전에서는 복잡한 구조를 만드는데 쓰이는 각각의 표준화한 부품이나 독립적인 단위
  • 여러 패키지가 서로 단단히 커플링되어 있으면 그 중 하나를 다른 작업에 재사용하기가 아주 어려워짐
  • 아키텍쳐를 논할 때 클래스, 함수처럼 코드를 묶어놓은 덩어리를 모듈성이라고 할때가 많음
  • 물리적인 구분이라고 보기는 힘든데 모놀리식에서는 클래스를 한 덩이루 묶어도 상관없지만 아키텍쳐를 다시 만들때는 모놀리식을 나눌때 걸림돌이 됨
  • 대부분의 언어에는 변수, 함수, 메서드 등을 구성하는 데 필요한 네임스페이스 역할을 하는 모듈성 메커니즘이 있음
  • 모듈구조가 물리적으로 반영되기도 하는데 자바 패키지는 클래스파일의 물리적인 디렉터리 구조를 그대로 나타냄

자바, 패키지, 모듈성

  • 자바는 패키지라는 네임스페이스 메커니즘을 도입하면서 물리적인 디렉터리 구조가 패키지명과 일치하도록 강제했음
  • 운영체제의 파일 시스템의 속성을 이용해서 모호함이 생길일을 원천봉쇄 한 것임
  • 초기에는 이름 충돌가능성이 전혀 없어서 좋았으나, 프로젝트가 커질수록 프레임워크와 디렉터리 구조에 맞춰서 탐색해야 하기 때문에 재사용 가능한 자산을 구축하기 어려웠음
  • JAR 메커니즘을 추가하고 아카이브 파일이 클래스패스에서 디렉터리 구조 역할을 하도록 허용함

모듈성을 측정하는 방법: 응집

  • 응집은 한 모듈의 파트가 동일한 모듈 안에 얼마나 포함되어 있는지를 나타냄
  • 모듈을 구성하는 파트가 서로 얼마나 연관되어 있는가에 대한 것임
  • 기능적응집, 순차적응집, 소통적응집, 절차적응집, 일시적응집, 논리적응집, 동시적응집
  • 카이댐버와 케메러가 개발한 "메서드의 응집 결여도(LCOM)"
  • LCOM은 아키텍쳐 스타일을 전환하기 위해 코드베이스를 분석하는 아키텍트에게 유용함
  • LCOM은 구조적 응집 결여도를 찾는것이지 어떤 조각들이 서로 잘 맞는지 논리적으로 찾는것은 아님

커플링

  • 코드베이스의 커필링은 그래프 이론에 기반한 분석 도구들이 많음
  • 구심커플링은 코드로 유입되는 접속수를, 원심커플링은 다른 코드로 유출되는 접속수를 나타냄

추상도, 불안정도

  • 추상도는 추상아티팩트(추상클래스, 인터페이스)와 구상아티팩트(구현체)의 비율, 구현대비 추상화의 정도를 나타냄

  • 추상화를 전혀 하지 않는다면 main 메서드에 모든 코드가 몰아 넣어지고, 너무 추상화하면 코드가 서로 어떻게 연결되어 있는지 개발자가 파악조차 어려움

  • 추상도는 추상요소의 합을 구상요소의 합으로 나눠서 구한다. 그래서 구상요소가 많아질수록 0에 가까워진다.

  • 불안정도는 원심커플링 / (원심커플링+구심커플링) 으로 구한다. 변동성을 의미하므로 불안정도가 높은 코드베이스는 변경시 커플링이 높아 더 깨지기 쉽다.

  • 여러 다른 클래스를 호출해서 작업을 위임하는 클래스는 호출되는 메서드중 하나라도 변경된다면 호출하는 클래스 또한 잘못될 확률이 높다.

메인시퀀스로부터의 거리

  • 메인시퀀스는 추상도와 불안정도 사이의 이상적인 관계를 나타낸다.
  • 메인 시퀀스로부터의 거리는 추상도와 불안정도 사이의 이상적인 관계를 나타낸다.
  • 개발자는 후보 클래스를 그려서 이상적인 선에서 얼마나 떨어져 있는지 거리를 잰다. 오른쪽 위로 치우친다면 추상화를 너무 많이해서 사용하기 어려운 코드이고, 왼쪽 아래로 치우친다면 추상화를 거의 하지 않아서 관리하기 힘든 코드라고 해석된다.

커네이선스

  • 두 컴포넌트 중 한쪽이 변경될 경우 다른 쪽도 변경해야 전체 시스템의 정합성이 맞는다면 이들은 커네이선스를 갖고 있는 것이다.

정적 커네이선스: 코드 레벨의 커플링

  1. 명칭 커네이선스: 여러 컴포넌트의 엔티티명이 일치해야 한다.
  2. 타입 커네이선스: 컴포넌트의 엔티티 타입이 일치해야 한다.
  3. 의미 커네이선스, 관례 커네이선스: 여러 컴포넌트에 걸쳐 어떤 값의 의미가 일치해야 한다. 상수로 선언하지 않고 변수로 숫자를 하드코딩한 코드베이스에서 흔히 발견된다.
    예를 든다면,
int TRUE = 1
int FALSE = 0
  1. 위치 커네이선스: 컴포넌트는 매개변수의 순서가 일치해야 한다.
  2. 알고리즘 커네이선스: 컴포넌트의 특정 알고리즘은 서로 일치해야 한다. 예를 들면, 서버와 클라이언트에서 사용되는 보안 해시 알고리즘은 같은것을 사용해야 한다.

동적 커네이선스: 런타임때의 커플링

  1. 실행 커네이선스: 컴포넌트의 실행 순서가 매우 중요한 경우
  2. 시점 커네이선스: 실행중인 두 스레드가 경합 조건이 발생하는 경우
  3. 값 커네이선스: 다수의 값들을 함께 변경할때 발생하는 경우, 꼭지점 4개로 사각형을 정의했다면 한쪽의 꼭지점만 무단으로 수정하면 안된다. 트랜잭션도 흔한 예로 전체 값들을 한 번에 바꾸거나 아무 값도 바꾸지 않아야 한다.
  4. 식별 커네이선스: 여러 컴포넌트가 동일한 엔티티를 참조할 때 발생, 두 컴포넌트가 분산 큐 같은 자료 구조를 공유하여 업데이트 하는 경우가 예
  • 일반적으로 런타임은 효과적인 분석 도구가 많지않아서 아키텍트는 동적 커네이선스를 파악하기가 쉽지는 않음

커네이선스 속성

  • 강도: 개발자가 어떤 유형의 커네이선스를 얼마나 쉽게 리팩터링 할 수 있는지에 따라 강도를 결정한다. 정적 커네이선스를 간단히 코드 분석을 하면 개선이 가능하기 때문에 아키텍트는 동적 커네이선스보다 정적 커네이선스를 선호한다.
  • 지역성: 코드베이스의 모듈들이 서로 얼마나 가까이 있는가이다. 모듈을 서로 떨어뜨렸을때 커플링이 안좋아지는 형태의 커네이선스라면 가까이 붙여놓아서 개선 할 수 있다. 개발자는 강도와 지역성을 함께 고민해야 한다.
  • 정도: 커네이선스가 소수의 클래스에 영향을 미치는가 아니면 수많은 클래스에 영향을 미치는가에 관한 것임. 일반적으로 이 값이 작아야 좋음.

페이지 존스의 모듈성 개선 방법

  1. 시스템을 캡슐화 한 요소들로 잘게 나누어 전체 커네이선스를 최소화한다.
  2. 캡슐화 경계를 벗어나는 나머지 커네이선스를 모조리 최소화한다.
  3. 캡슐화 경계 내부에서 커네이선스를 최대화한다.

짐 웨이리치의 커네이선스에 대한 조언

  • 정도의 규칙: 강한 형태의 커네이선스를 보다 약한 형태의 커네이선스로 전환하라.
  • 지역성의 규칙: 소프트웨어 엘리먼트간의 거리가 멀어질수록 보다 약한 형태의 커네이선스를 사용하라.

커플링과 커네이선스 메트릭의 통합

  • 페이지-존스가 정적 커네이선스라고 밝힌 것들은 유출/유입 커플링 정도를 나타낸다.
  • 구조적 프로그래밍은 들어오고 나가는 것에 관심이 있지만, 커네이선스를 요서가 어떻게 커플링되는지에 주목한다.

커네이선스의 문제점

  1. 메트릭은 아키텍쳐 구조보다는 저수준의 코드, 코드 품질, 정리상태 위주를 관찰하게 된다.
  2. 커네이선스 자체는 아키텍트가 내려야 할 근본적인 결정에 관한 문제를 다루지는 않는다.

모듈에서 컴포넌트로

책에서는 모듈이라는 일반 용어로 표현하지만, 많은 플랫폼에서는 컴포넌트 형태로 지원한다.

profile
Frontend Developer

0개의 댓글