엔터프라이즈 애플리케이션 또는 시스템을 구축할 때 비즈니스의 요구사항에 맞춰 선택된 품질 특성을 고려하면서 진행한다. 그러한 품질 특성 중에 유지보수성도 있다. 아키텍처의 품질 특성으로 유지보수성이 선택되든 안 되든 개발자로서 가장 신경 써야 하는 부분은 유지보수성이라 생각한다. 정도의 차이일 뿐이다.

개발자가 유지보수성을 생각해야 하는 이유는 명확하다. 사람이 변경되더라도 비즈니스는 계속되어야 한다. 그런 전제 조건하에 고객에게 기능을 지속해서 빠르게 전달하는 핵심 키는 유지보수성이다. 유지보수성이 고려되지 않은 애플리케이션은 시간이 지날수록 고객에게 전달되는 기능의 속도가 늦어지고, 고객과 개발자 모두를 고통스럽게 만든다.

비록 많다고 할 수 없는 경험일지라도, 지금까지 경험한 바와 여러 가지 서적들을 통해 내가 유지보수성 관련해서 얻은 바는 다음을 되도록 준수해야 한다는 것이다. 물론 이것 자체가 절대적이지 않다. 모든 게 상대적이다. 불변하지 않는 건 ‘경우에 따라 다르다’이다. 다만 다음의 것들이 어떤 상황이더라도 유지보수성에 대한 확률을 좀 더 높인다는 것은 변함없다.

클린 아키텍처(Clean Architecutre)

비즈니스 도메인은 해당 영역에만 관심 있어야 하고 그 외 기술적인 영역에는 관심이 없어야 한다. 이게 핵심이다. 도메인 로직들이 앱이나 웹의 화면 또는 해당 기술적 요소에 따라 영향을 주거나 받으면 처음에는 빠른 개발이 되는 것처럼 느끼겠지만 결국에는 아주 작은 수정에도 무엇이 잘못되었는지 파악하기 힘든 상황을 만들게 된다. 이게 클린 아키텍처의 요약 내용이다.

클린 아키텍처 중에서 가장 유명한 것이 헥사고날 아키텍처(Hexagonal Architecture)다. Port와 Adapter라고도 불리기도 한다. Port와 Adapter의 역할을 명시함으로써 전체적인 명확성을 제공한다. 그런 명확성을 통해 도메인 로직이 외부 영향에 휩쓸리지 않도록 환경을 조성해 준다.

단순성 (Simplicity)

작성하는 코드는 단순해야 한다. 단순하게 유지하기 위해서는 SRP(Single-responsibility principle)CCP(Common Closure Principle)을 준수해야 한다. 그러기 위해서 여러 파일들 또는 여러 개의 함수(메서드)들을 생성하는 것에 대해 두려워 해서는 안 된다. 파일 1개는 1개의 클래스만 담고 1개의 클래스는 1개의 일만 하도록 사고하면서 코드를 작성하자.

함수 같은 경우는 줄 수가 10줄을 넘어가지 않도록 작성해 보자. 함수 안에는 많을 경우 딱 1개의 조건문만 담도록 해보자. 이런 사고를 통해 단순하게 구성하면서 가독성이 높은 코드를 만들 수 있는 환경이 구성된다.

성급한 추상화도 하지 않는다. ‘미래에 쓰일 것이다’라는 가정을 통해 성급한 추상화를 하는 것은 복잡성만 올린다. 현재의 요건을 잘 표현하면서 유지보수성이 높은 코드를 구성하고 추후 관련 요구사항이 생겼을 때 추상화 필요 여부를 판단하고 진행한다.

성급한 성능 최적화도 하지 않는다. 시스템은 사람이 유지보수한다. 사람이 읽고 빠르게 이해할 수 있게 해주는 코드가 훨씬 좋다. 성능 최적화는 그로 인해 실제 문제를 일으키거나 확실한 근거가 있는 경우에만 성능 최적화를 한다.

경험한 몇몇 분들은 단순하게 만드는 것이 코드 작성에 실력이 없다는 것을 보여준다는 착각 때문에 화려한 기법을 사용하는 것 같다. 또는 잘 알지 못하더라도 트렌디한 것을 사용함으로써 자신의 우월감을 보여주려고 하는 것 같다. 그런 함정에 빠지지 않았으면 한다.

TDD

코드 커버리지를 100% 가깝게 유지할 수 있도록 도움을 주는 행동 방법론이다. 코드 커버리지를 100% 만든다고 해서 버그가 없다는 것을 증명하지 않는다. 그런 관점으로 접근하는 것을 원하지 않는다. TDD를 통해 코드 커버리지를 100%를 유지한다는 것은 실제 수행이 되는 동작이 되는 코드만 작성한다는 의미다. 그런 의미론으로 접근해야 한다.

그리고 TDD를 통해 좀 더 테스트 가능한 코드를 만들 수 있다. 다양한 예외 케이스들도 생각하게 만들어 준다. TDD는 올바른 철학에 따라 행동하는 과정을 통해야만 좋은 결과를 얻을 수 있다. 단순히 형식적으로 TDD를 하는 것은 하지 않는 게 좋다.

테스트

깨지지 않는 테스트 코드 그리고 효과적인 TDD를 위해서는 블랙박스 테스트를 유지해야 한다. 블랙박스 테스트가 테스트 영역에서 클린 아키텍처다. 즉, mocking 같은 라이브러리를 통해 검증할 때 어떤 함수를 몇 번 호출했는지, 어떤 순서로 호출했는지와 같은 검증은 절대 해서는 안 된다. 이는 화이트박스 테스트다.

블랙박스 테스트를 유지하기 위해서는 단위 테스트 작성도 클래시컬 스쿨(Classical school)로 작성되어야 한다. 단 모든 것을 클래시컬 스쿨 방식으로 작성할 수는 없다. 경우에 따라 런던 스쿨(London school) 방식도 활용해야 한다. 주는 클래시컬 스클로 보조적으로 런던 스쿨을 사용해야 한다.

그 외

명확한 API 작성 방법, 예외를 다루는 법, 검증하는 법, 로깅 방법 등도 엄격한 규칙이 구성되어서 적용되어야 한다. 그렇지 않을 경우 클린 아키텍처를 지향하더라도 위로 인해 균열이 깨지기 쉽다.

예로 예외의 경우는 대략 다음과 같은 규칙을 둔다. Java 같은 예외를 사용하는 언어의 예이다.

  • 기술(technical)적인 부분은 언어 고유의 기본 exception을 이용한다. 비즈니스와 관련된 것이라면 특정 상위 예외(예 BizException)을 상속받은 특정 Exception을 이용한다.
  • 비즈니스 예외를 확실하게 보여주는 Exception을 명명해서 사용한다. 즉, BizException과 같이 일반적인 Exception은 사용하지 않는다.
  • Throw early, catch late. 예외를 적절하게 대응하지 않을 것이라면 절대로 catch 하지 않는다.
  • Exception 발행 시 불필요한 로그를 남기지 않는다. 예외 관련 context는 예외 안에 포함한 후 필요로 하는 지점에서 활용하도록 한다.

검증 같은 경우도 다음과 같은 예를 들 수 있겠다.

  • public으로 노출된 함수는 반드시 전달 되는 값을 검증하고 private으로 관리되는 함수는 검증 하지 않는다.
  • 검증 시 Google Guava의 예시처럼 검증 결과에 맞게 예외를 사용한다.

끝으로

상위 개념 또는 고차원 개념으로만 작성했다. 이것 외에도 지키면 좋을 규칙들이 더 있다.

향후에는 상세 내용에 대해 공유하고자 한다. 상세 내용은 실제 엔터프라이즈 애플리케이션을 구축하는 환경에서 겪을 수 있는 예시를 가지고 하고자 한다.

CC by-nc-nd