좋은 아키텍처를 어떻게 볼 것인가?

우리는 종종 ‘좋은 아키텍처’나 ‘유지보수하기 쉬운 코드’를 이야기하지만, 이런 평가는 주관적으로 흐르기 쉽습니다. 코드의 구조적 건강 상태를 조금 더 객관적으로 볼 방법은 없을까요? 로버트 C. 마틴(Robert C. Martin)은 이 질문에 답하기 위해 몇 가지 지표를 제시했습니다.

그중 메인 시퀀스로부터의 거리(Distance from the Main Sequence) 는 모듈(컴포넌트, 패키지 등)이 추상성과 안정성 사이에서 어느 정도 균형을 이루고 있는지 보는 지표입니다. 이 지표를 이해하려면 먼저 추상도(Abstractness)불안정도(Instability) 를 알아야 합니다.

1. 추상도 (Abstractness): 얼마나 유연한가?

추상도(A) 는 모듈이 얼마나 많은 추상적인 요소(추상 클래스, 인터페이스)를 포함하고 있는지를 나타내는 척도입니다. 즉, 모듈의 ‘구현’ 대비 ‘추상화’의 비율을 측정합니다.

공식은 다음과 같습니다:

$$ A = \frac{\text{모듈 내 추상 클래스와 인터페이스의 수}}{\text{모듈 내 전체 클래스의 수}} $$
  • A = 0: 모듈에 추상 클래스나 인터페이스가 전혀 없고, 오직 구체적인 구현 클래스만 존재합니다. 이 모듈은 확장하기 어렵고 경직되어 있을 가능성이 높습니다.
  • A = 1: 모듈이 오직 추상 클래스와 인터페이스로만 구성되어 있습니다. 이 모듈은 매우 유연하고 확장성이 뛰어납니다.

추상도가 높을수록 모듈은 변화에 더 잘 적응할 수 있지만, 지나치게 추상적이면 실제 내용이 없는 껍데기가 될 수도 있습니다.

2. 불안정도 (Instability): 얼마나 쉽게 변하는가?

불안정도(I) 는 모듈이 다른 모듈의 변경에 얼마나 영향을 받기 쉬운지를 나타내는 척도입니다. 이는 모듈의 의존성 관계를 통해 계산됩니다.

이를 이해하기 위해 두 가지 커플링 개념이 필요합니다.

  • 구심 커플링 (Afferent Coupling, Ca): 들어오는 의존성. 얼마나 많은 외부 모듈이 이 모듈 에 의존하고 있는지를 나타냅니다. 이 값이 높을수록 모듈은 책임감 있고 안정적(stable) 이라고 말합니다. (변경 시 파급 효과가 크기 때문)
  • 원심 커플링 (Efferent Coupling, Ce): 나가는 의존성. 이 모듈 이 얼마나 많은 외부 모듈에 의존하고 있는지를 나타냅니다. 이 값이 높을수록 모듈은 변덕스럽고 불안정(instable) 하다고 말합니다. (외부의 변경에 쉽게 영향을 받기 때문)

불안정도를 계산하는 공식은 다음과 같습니다:

$$ I = \frac{C^e}{C^a + C^e} $$
  • I = 0: 모듈에 대한 들어오는 의존성만 있고 나가는 의존성은 없습니다. 이는 매우 안정적인 상태로, 다른 모듈에 영향을 줄 수는 있지만 자신은 외부로부터 영향을 거의 받지 않습니다.
  • I = 1: 모듈이 다른 모듈에 의존하기만 하고, 이 모듈에 의존하는 다른 모듈은 없습니다. 이는 매우 불안정한 상태로, 외부 모듈의 변경에 직접적으로 영향을 받습니다.

3. 메인 시퀀스로부터의 거리 (Distance from the Main Sequence)

이제 두 지표를 결합해 메인 시퀀스로부터의 거리(D) 를 계산합니다. 이 값은 모듈이 얼마나 균형 잡힌 상태에 가까운지 보여줍니다.

공식은 다음과 같습니다:

$$ D = |A + I - 1| $$
  • D = 0: 모듈이 메인 시퀀스 위에 정확히 위치하며, 추상도와 안정성 간의 균형이 가장 이상적인 상태입니다.
  • D = 1: 모듈이 메인 시퀀스에서 가장 멀리 떨어져 있으며, 구조적으로 문제가 있을 가능성이 매우 높습니다.

그래프로 보면 의미가 더 분명해집니다.

  • x축: 불안정도 (I) - 오른쪽으로 갈수록 불안정
  • y축: 추상도 (A) - 위로 갈수록 추상적
  • 메인 시퀀스: A + I = 1을 만족하는 대각선. 이 선 위에 있는 모듈들이 가장 바람직한 구조를 가집니다.

쓸모없는 구역과 고통의 구역

메인 시퀀스에서 멀리 떨어진 모듈들은 두 가지 위험 지대에 속하게 됩니다.

1. 고통의 구역 (Zone of Pain)

  • 위치: 그래프의 왼쪽 아래 (A=0, I=0 에 가까움)
  • 특징: 매우 안정적 이면서 동시에 매우 구체적 인 모듈입니다.
  • 문제점: 많은 다른 모듈들이 이 모듈에 의존하고 있어 변경하기가 매우 어렵지만(안정적), 추상화가 전혀 되어 있지 않아 확장도 불가능합니다(구체적). 이런 모듈은 시스템 전체를 경직되게 만드는 주범이 됩니다.
  • 예시: 데이터베이스 스키마와 강하게 결합된 구체적인 클래스(UserDAO)가 있고, 시스템의 50개 다른 클래스가 이 UserDAO를 직접 사용하고 있다고 상상해 보세요. UserDAO를 변경하는 것은 엄청난 고통을 수반할 것입니다.

2. 쓸모없는 구역 (Zone of Uselessness)

  • 위치: 그래프의 오른쪽 위 (A=1, I=1 에 가까움)
  • 특징: 매우 추상적 이면서 동시에 매우 불안정 한 모듈입니다.
  • 문제점: 이 모듈은 인터페이스와 추상 클래스로 가득 차 있지만(추상적), 아무도 이 모듈을 사용하지 않으며(들어오는 의존성 없음), 오히려 다른 여러 구체적인 모듈에 의존하고 있습니다(불안정). 즉, 아무에게도 쓰이지 않는 과도한 추상화의 결과물입니다.
  • 예시: 아무도 구현하지 않고 사용하지도 않는 수많은 인터페이스만 모아놓은 패키지를 생각할 수 있습니다.

결론: 균형을 향한 리팩토링

메인 시퀀스로부터의 거리 는 우리에게 중요한 교훈을 줍니다. 좋은 아키텍처는 단순히 추상적이거나 안정적이기만 한 것이 아니라, 두 특성 간의 적절한 균형 을 이루어야 한다는 것입니다.

  • 안정적인 모듈 은 변경하기 어려우므로, 변화에 유연하게 대처할 수 있도록 추상적이어야 합니다. (예: 프레임워크의 인터페이스)
  • 구체적인 모듈 은 자주 변경될 수 있으므로, 다른 모듈에 미치는 영향을 최소화하기 위해 불안정해야 합니다. (예: 비즈니스 로직 구현체)

이 지표를 쓰면 시스템의 각 모듈을 그래프 위에 배치해보고, ‘고통의 구역’이나 ‘쓸모없는 구역’에 가까운 모듈을 찾을 수 있습니다. 그런 모듈은 추상화를 추가하거나 의존성 방향을 조정하는 식으로 메인 시퀀스에 가깝게 옮기는 리팩토링 후보가 됩니다.


이 글은 AI의 도움을 받아 교정 및 정리되었습니다.