좋은 OOP 설계에서 지켜져야하는 규칙인 SOLID 중 S인 규칙으로, 하나의 모듈은 하나의 책임을 가져야한다는 원칙을 말한다.
클래스는 단 한개의 책임을 가져야한다.
하나의 모듈은 오직 하나의 액터에 대해서만 책임져야한다.
클래스를 변경하는 이유는 단 한개여야 한다.
여기서 책임은 액터에 대한 책임을 의미한다. 하나의 액터에 대해 하나의 책임을 지는 객체를 정의하고 사용하라는 것이다. 액터는 시스템과 상호작용하는 시스템 외부의 어떤 존재를 뜻하는 말로, 시스템의 이해관계자로 정의할 수 있다. 쇼핑 앱을 예로 들면, 물건을 구매하려는 고객이 액터이다.
이 정의는 모듈의 응집도를 높이기 위해 사용된다. 단일 액터를 책임지는 코드들을 묶어 응집도를 높여 단일 책임 원칙을 준수함을 통해 모듈의 응집도를 높이는 것이다.
이렇게 모듈의 응집도를 높여 하나의 액터에 대해 하나의 책임을 지는 객체를 정의한다면, 단일 액터만이 단일 객체에 대해 변경할 이유를 가질 수 있다.
SRP를 지켜야하는 이유
한가지 예시를 들며 SRP를 지키는 것이 무엇이며 어떻게 개발 비용을 증가시키는지 알아보자.
만약 도서관의 도서 관리 시스템을 맡게 되었고, 아래와 같은 유즈케이스 다이어그램을 도출하였다고 해보자.
이 유즈케이스 중 대여, 연체관리, 연체금 표시를 묶어 하나의 rental이라는 클래스에 기능을 구현하였고, 회원은 연체금이 10000원이 넘어가면 더이상 책을 대여할 수 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Injectable } from '@nestjs/common';
@Injectable()
export class RentalService {
async userRentalBook() {
// 연체료 계산
// 대여 로직 수행
}
async getUserArrears() {
// 연체료 계산
// 연체료 표시
}
...
}
위의 두 함수, 책을 대여하는 함수와 연체금을 표시하는 함수는 책의 연체금을 계산하는 로직은 각 메서드 내부에 있다.
위 코드는 잘동작한다. 하지만, 만약 어느날 연체금 정책이 변경되었다고 해보자. 원래는 모든 책이 연체일 하루당 1000원이었지만, 사람들이 많이 읽는 책은 1500원, 잘 읽지 않는 책은 500원으로 변경되었다.
이때 문제가 발생한다. 대여함수와 연체금 표시에서 각각 연체금 계산 로직을 새로 수정해야한다.
원인은?
원인은 하나의 클래스에 속한 두 함수는 연체금 계산이라는 로직을 공유하지만 두 함수가 제공하는 기능의 책임이 다른 곳에 있기 때문이다.
책 대여 함수는 회원 액터에 대한 책임이 있고, 연체금 표시는 관리자 액터에 대한 책임이 있다. 이렇게 두 개의 액테에 대한 책임이 한 클래스에 부여되어 변경사항을 반영해야하는 범위가 넓어진 것이다.
해결책
단일책임원칙을 지켜 대여는 회원 액터만이, 연체금 표시는 사서 액터만이 사용하도록 변경해주면 된다. RestalService
클래스에 있는 두 메서드를 완전히 분리하면 해결할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Injectable()
export class ArrearsService {
async calcUserArrears() {
// 연체금 계산
}
async getUserArrears() {
// 연체금 표시
}
...
}
@Injectable()
export class RentalService {
async userRentalBook() {
// 책 대여
}
...
}
연체금과 관련된 연체금 계산 로직 및 연체금 표시 메서드는 ArrearsService
에 위임하고, 대여와 관련된 메서드는 RentalService
에 위임하였다. 이로써 ArrearsService
는 누가 대여하는지 알지 못한다. 단순히 연체일에 따라 연체금을 표시하도록 변경되었다. RentalService
는 연체금 계산 방식에 대해 알지 못한다. 단순히 대여가능 여부만을 알 수 있다.
이렇게 메서드를 분리한 후 아까와 같은 변경사항이 왔다고 해보자. ArrearsService
에 연체금 계산 메서드가 변경되겠지만, RentalService
는 변경하지 않아도 된다. 어떻게 계산이 되든 10000원이 넘어가는 연체금이라면 대여할 수 없다. 변경사항은 연체금에 대한 수정사항이었고, 관리자 액터로부터 야기된 수정사항이다.
출처
https://velog.io/@qjqdn1568/SOLID-%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99-SRP