본문 바로가기
Concepts/SW Architecture

설계원칙 - SOLID(SRP)

by ocwokocw 2021. 2. 10.

- 이 글은 로버트 C.마틴의 Clean Architecture를 기반으로 작성되었습니다. (가능하면 책을 읽어보는것을 추천한다.)

- 개요

단일 책임 원칙은 가장 많은 오해를 사고 있는 원칙이다. 이름만 보면 마치 하나의 모듈은 하나의 일만 해야하는 것처럼 느껴진다. 하지만 이는 오해이다. 하나의 모듈은 하나의 액터(사용자 및 이해관계자)에 대해서만 책임져야 한다. 모듈이란 보통의 경우엔 소스파일이다. SRP를 위반하는 원칙들을 살펴보면서 SRP를 이해해보자.


- 징후: 우발적 증복

급여 어플리케이션에서 Employee 클래스가 있고, 해당 클래스에서 calculatePay(), reportHours(), save() 메소드를 제공한다고 해보자.

이 클래스는 SRP를 위반한다고 할 수 있는데, diagram에서 보다시피 3 명의 액터를 책임지기 때문이다.

  • calculatePay() 메소드는 회계팀에서 기능을 정의하며, CFO 보고를 위해 사용한다.
  • reportHours() 메소드는 인사팀에서 기능을 정의하며, COO 보고를 위해 사용한다.
  • save() 메소드는 DBA가 기능을 정의하며 CTO 보고를 위해 사용한다.

 

만약 calculatePay() 메소드와 reportHours() 메소드가 정규 근무시간을 계산하는 regularHours() 메소드를 공유한다고 가정해보자.

이제 CFO 팀에서 정규 근무시간을 계산하는 정책을 변경하여 개발자에게 수정을 요청한다. 개발자는 calculatePay() 에서 regularHours() 메소드를 통해 정규 근무시간을 계산하고 있음을 발견한다. regularHours()를 수정하고 테스트 후 배포한다.

 

regularHours()를 사용하고 있던 COO 팀은 갑자기 하루아침에 달라진 수치에 멘탈이 붕괴된다. 이런 문제는 서로 다른 액터들(CFO, COO)에 의존하는 코드를 응집시켰기 때문에 발생한다. SRP 원칙에 의해 서로 다른 액터가 의존하는 코드를 분리하였으면 예방할 수 있는 문제였다.


- 징후: 소스충돌

DBA가 속한 CTO팀에서 데이터베이스의 Employee 테이블 스키마를 수정하는 동시에 COO 팀에서는 reportHours()를 수정한다. 각 팀의 개발자가 Employee 클래스를 동시에 수정한다.

 

기능을 완성한 후 소스가 충돌이 일어난다. 물론 두 개발자가 협력하면 소스를 고칠수는 있다. 변경범위가 작고 소스코드 관리 시스템을 사용하고 있다면 크게 어렵지 않은 일이다. 하지만 위험을 굳이 감수할 필요는 없다. 서로 다른 액터를 뒷받침하는 코드를 분리하면 이와 같은 참사를 피할 수 있을 것이다.


- 해결책

각 액터를 책임지는 3 메소드를 각 클래스로 추출하고, 추출된 3 클래스가 EployeeData를 공유하도록 변경해보자.

추출된 클래스들은 각각 하나의 액터를 담당하게 되었다. 이는 소스코드가 변경될 때 하나의 액터에 의해서만 변경되게 됨을 의미한다.

 

SRP가 적용된 위 다이어그램에서 세 가지 클래스에 대해 관리 및 추적을 해야한다는 단점이 있는데 퍼사드 패턴을 사용하면 이를 보완할 수 있다.


- 결론

단일 책임 원칙은 메소드와 클래스 수준의 원칙이다. 컴포넌트 수준에서도 SRP 형태가 등장한다. 

SRP는 하나의 일만 하는 것이 아니라 해당 모듈은 하나의 액터의 요구에 의해서만 변경되어야 한다는것을 잘 기억하도록 하자.

댓글