[소프트웨어 아키텍처] 단일책임 원칙(SRP)이란 무엇인가?

단일 책임 원칙이라는 것의 정의는 아래와 같다.

하나의 모듈은 하나의, 오직 하나의 사용자 또는 이해관계자에 대해서만 책임을 져야 한다.

하나의 모듈은 하나의, 오직 하나의 액터에 대해서만 책임져야 한다.

단일 책임 원칙(SRP)을 위반 하는 사례

CASE1. 우발적 중복

아래는 급여 애플리케이션 Employee 클래스를 보여주고 있다. 이 클래스는 3가지 메서드 calculatePay(), reportHours(), save()를 가진다.

해당 구조는 SRP을 위반 하는 구조 이다. 왜냐하면 3가지 메소드가 서로 매우 다른 세명의 엑터를 책임지기 때문이다.

  • calculatePay() 메서드는 회계팀에서 기능을 정의하며, CFO 보고를 위해 사용한다.
  • reportHours() 메서드는 인사팀에서 기능을 정의하고 사용하며, COO 보고를 위해 사용된다.
  • save() 메서드는 데이터베이스 관리자 DBA가 기능을 저의하고 CTO 보고를 위해 사용 한다.

개발자가 이 세 메서드를 Employee라는 단일 클래스에 배치하여 세 액터가 서로 결합되어 버렸다. 이 결합으로 인해 CFO 팀에서 결정한 조치가 COO팀이 의존하는 무언가에 영향을 줄 수 있다.

예를 들어 calculatePay() 메서드와 reportHours() 메서드가 초과 근무를 제외한 업무 시간을 계산하는 알고리즘을 공유 한다고 해보자. 그리고 개발자는 코드 중복을 피하기 위해 이 알고리즘을 regularHours()라는 메서드에 넣었다고 해보자.

이제 CFO 팀에서 초과 근무를 제외한 업무 시간을 계산하는 방식을 약간 수정하기로 결정했다고 하자. 반면 인사 담당하는 COO 팀에서는 초과 근무를 제외한 업무 시간을 CFO 팀과는 다른 목적으로 사용하기 때문에 이 같은 변경을 원하지 않는다고 해보자.

이 변경을 적용하는 업무를 할당 받은 개발자는 calculatePay() 메서드가 편의 메서드인 regulateHours()를 호출한다는 사실을 발견한다. 하지만 안타깝게도 이 함수가 reportHours() 메서드에서도 호출된다는 사실은 눈치채지 못한다.

개발자는 요청된 변경사항을 적용하고 신중하게 테스트를 한다. CFO 팀은 새로운 메서드가 원하는 방식으로 동작하는지 검증하고 시스템에 배포된다. 물론 COO 팀에서는 이러한 일이 벌어지고 있다는 사실을 알지 못한다.

COO 팀 직원은 reportHours() 메서드가 생서한 보고서를 여전히 이용한다. 하지만 이제 이 보고서에 포함한 수치들은 엉터리다. 마침내 문제가 발견하고 COO는 격노한다. 잘못된 데이터로 수백만 달러의 예산이 지출되었기 때문이다.

이와 같은 상황은 서로 다른 액터가 의존하는 코드를 너무 가까이 배치했기 때문에 발생한다. SRP는 서로 다른 액터가 의존하는 코드를 서로 분리하라고 말한다.

CASE 2.병합

소스 파일에 다양하고 많은 메서드를 포함하면 병합이 자주 발생하리라고 짐작하기는 어려운 일이 아니다. 특이 이들 메서드가 서로 다른 액터를 책임진다면 병합이 발생할 가능성은 확실히 더 높다.

예를 들어, DBA가 속한 CTO 팀에서 데이터베이스의 Employee 테이블 스키마를 약간 수정하기로 결정했다고 해보자. 이와 동시에 인사 담당자가 속한 COO 팀에서는 reportHours() 메서드의 보고서 포맷을 변경하기로 결정했다고 해보자

두명의 서로 다른 개발자가, 그리고 아마도 서로 다른 팀에 속했을 두 개발자가 Employee 클래스를 체크아웃 받은 후 변경사항을 적용하기 시작 한다. 이들 변경사항은 서로 충돌한다. 결과적으로 병합이 발생한다.

이런 케이스를 벗어 나는 방법은 서로 다른 액터를 뒷받침하는 코드를 서로 분리하는 것이다.

해결책

이러한 중복 문제를 해결하기 위한 해결책은 다음 글에서 기술 한다.

관련 글 보기